
#include "Common.h"
#include "String.h"
#include "SharedPtr.h"
#include "ResourceManager.h"
#include "Database/DatabaseEnv.h"
#include "StringConverter.h"
#include "NGLog.h"
#include "MersenneTwister.h"
#include "ScriptMgr.h"
#include "Threading/Mutex.h"
#include "Vector3.h"
#include "Game.h"
#include "WorldPacket.h"
#include "WSSocket.h"
#include "Towns.h"
#include "TownManager.h"
#include "WorldPacket.h"
#include "Message.h"
#include "Mails.h"
#include "PGWorldAIInterface.h"
#include "PGAIScript.h"
#include "PGPubStruct.h"
#include "PGRuleManager.h"
#include "CenterBankManager.h"
#include "VipCardManager.h"
#include "GameDefine.h"
#include "Tools.h"
#include ENUM_PATH
#include XMLDATA_MGR_PATH
#include PROTOCOLS_MGR_PATH
#include LOG_MGR_PATH
#include LOGIC_MGR_PATH
#include "UserGameLogsManager.h"
#define INIT_POS 255
#define PLAYER_NUM 4 ///座位数量
#define TYPENUM 32


namespace AIScript
{
	#define INITPOS 100
	//-----------------------------------------------------------------------
	PGChannelInterface::PGChannelInterface(Resource *channel) : AIChannelBaseInterface(channel)
	{
		m_AIType = AITYPE_WCHANNEL;
	}
	//-----------------------------------------------------------------------
	PGChannelInterface::~PGChannelInterface(void)
	{

	}

/***********************************************数据对象初始化*********************************************/
	void PGChannelInterface::initialize(void)
	{
		m_lstChars.clear();
		m_chinNum = 0;
		ResetData();
		m_dealStartPos = INITPOS;
		m_nOnceSend = false;
		m_bIsAllCalc = false;
		m_nSpeakPos = INITPOS;
		m_status_endtimer = now();
		m_status_waitimer = now();
		m_beginShowTime = now();
		m_dices = 0;
		m_dices1 = 0;
		m_dices2 = 0;
		m_cutplayer = 0;
		m_nOptTimes = 0;
		m_nBnkerTimes = 0;
		m_curState = en_ChannelState_Prepare;
		m_nCanGetBankerNum =0;
		m_lastCheckTime = 0;
		m_curChipLimit = 0;
		m_contOrstop = false;
		m_bCompare   = false;
		m_bAddCenterBattleLog = true;
		m_bVoting = false;

		m_pTown = sTownMgr.getByHandle(m_Unit->getUInt32Field("town_id"));
		assert(!m_pTown.isNull());
		m_bWantBanker.clear();
		m_bWantBanker.assign(4, en_LootBanker_Init);
		InitCenterBattleInto();
	}
	//-----------------------------------------------------------------------
	void PGChannelInterface::ResetData()
	{
		m_curWaitOperator = 0;
		m_beginWaitTime = 0;
		m_bankerAnswer = 0;
		m_lastSaveTime = 0;
	}
	//-----------------------------------------------------------------------
	void PGChannelInterface::Load()
	{
		m_mapVotePlayers.clear();
		m_mapFreePlayers.clear();
		m_lstOutCards.clear();
		m_nGetBankerMode = 0;
		m_nLastSitTime = 0;
		m_nVoteOverTime = 0;
		m_nVotePos = 0;
		m_nDissolveReson = 0;
		m_nFzPid = 0;
		m_nBasePoint = 0;
		m_nLimitLoop = 0;
		m_nLimitTime = 0;
		m_nTopTimes = 0;
		m_nGameID = 0;
		m_nGzid = 0;
		m_nMode = 0;
		m_nLoopId = 0;
		m_IsDjnn = 0;
		m_IsGz = 0;
		m_IsTWJ = 0;
		m_IsZDY = 0;
		m_nNumBar = 0;
		m_nGameStartTime = 0;
		m_strPlayJsonData = "";
		m_strPlayJsonDataCommon = "";
		m_nWaitPlayerStartTimer = 0;
		m_Gamenumber = 0;
		m_bVoting = false;
		m_bFirstStartGame = true;
		m_bGameOver = false;
		m_bPlaying = false;
		m_bFinishCalc = false;
		m_bIsAllCalc = false;
		m_bInitCenterData = false;
		m_nQiangZhuangBeiShu = 0;
		m_nLoopBankerMode = 0;
		m_nQiangBankerMode = 0;
		m_bComboBanker = false;
		m_CardIsEmpty  = true;
		uint32 town_id = m_Unit->getUInt32Field("town_id");
		m_Town = sTownMgr.getByHandle(town_id);
		m_nMaxPlayerNum = m_Town->getUInt32Field("max_num");
		PlayerPos.clear();
		
		for (int i = 0; i < 4; ++i)
		{
			PlayerPos.push_back(TablePlayer());
			PlayerPos[i].pos = i;
		}

		initialize();
		Log.Debug("PGChannelInterface::Load", "加载Load!!!!");
		HSM_INIT_(&PGChannelInterface::channel_init);
		Log.Debug("PGChannelInterface", "Channel[%u] Loaded!! ", m_Unit->getHandle());
		AIInterface::Load();
	}
	//-----------------------------------------------------------------------
	//初始化棋牌圈数据
	void PGChannelInterface::InitCenterBattleInto(void)
	{

			Json::Reader reader;
			Json::Value val;
			reader.parse(m_Unit->getStringField("info"), val);
			CenterBattle cb;
			if (val.isMember("cb_id"))
			{ // 组局ID
				m_btLog.cb_id = val["cb_id"].asUInt();
				sCenterBattleMgr.GetCenterBattle(m_btLog.cb_id, &cb);
				m_btLog.agent_id = cb.reg_from;
				m_nAAPay_ModelId = cb.data1;
				m_nAAPay_num = cb.data2;
				m_nPaymode = cb.pay_mode;
			}

			if (val.isMember("fz_pid"))
			{ // 房主PID
				m_nFzPid = val["fz_pid"].asUInt();
			}

			if (val.isMember("limit_loop"))
			{ // 限制轮次
				m_nLimitLoop = val["limit_loop"].asUInt();
			}

			if (val.isMember("limit_time"))
			{ // 限制时间
				m_nLimitTime = val["limit_time"].asUInt();
			}

			//附加数据
			if (val.isMember("extra_data"))
			{
				Json::Value val2 = val["extra_data"];
				if (val2.isMember("game_id"))
				{ // 游戏ID
					m_nGameID = val2["game_id"].asUInt();
					m_btLog.game_id = m_nGameID;
				}

				if (val2.isMember("gz_id"))
				{
					m_nGzid = val2["gz_id"].asUInt();
				}
			//---------------特殊牌--------------------
				if (val2.isMember("isDJNN"))
				{//地九靓靓
					m_IsDjnn = val2["isDJNN"].asUInt();
				}

				if (val2.isMember("isGZ"))
				{//鬼子
					m_IsGz = val2["isGZ"].asUInt();
				}

				if (val2.isMember("isTWJ"))
				{//天王九
					m_IsTWJ = val2["isTWJ"].asUInt();
				}

				if (val2.isMember("isZDY"))
				{//炸弹一
					m_IsZDY = val2["isZDY"].asUInt();
				}
			//----------------------------------------

				if (val2.isMember("typeDao"))
				{//杠数
					m_nNumBar = val2["typeDao"].asUInt();
				}

				if (val2.isMember("typeDi"))
				{ // 底分
					m_nBasePoint = val2["typeDi"].asUInt();
					if (m_nLoopId == 0)//防止每局都被初始化
						m_BaseScore = m_nBasePoint;
				}

				//m_nLoopBankerMode = 1; // 默认轮庄
				if (val2.isMember("typeQiangZhuang"))
				{ // 1 轮庄 2 抢庄 3 固定庄/房主庄
					m_nLoopBankerMode = val2["typeQiangZhuang"].asUInt();
				}

				if (val2.isMember("typeQieGuo"))
				{ // 封顶倍数
					m_nTopTimes = val2["typeQieGuo"].asUInt();
				}

				if (val2.isMember("mode"))
				{
					m_nMode = val2["mode"].asUInt();
					m_btLog.mode = m_nMode;
				}
				// 固定4人开局
				m_nMaxPlayerNum = 4;
			}
			Json::FastWriter w;
			// 房间ID
			val["join_code"] = m_Unit->getStringField("winner");
			// 开始时间
			val["start_time"] = m_nGameStartTime;
			// 当前轮次
			val["curr_loop"] = m_nLoopId;
			// 房费
			val["pay_num"] = cb.data2;

			m_strPlayJsonDataCommon = w.write(val);

			m_btLog.player_winLose.clear();
			m_bInitCenterData = true;
			Log.Debug("PGChannelInterface::InitCenterBattleInto", "channel[%u] m_nBasePoint[%u] m_nLimitLoop[%u] m_nLimitTime[%u]",
					m_Unit->getHandle(), m_nBasePoint, m_nLimitLoop, m_nLimitTime);

			m_specialtype.Init(m_IsZDY, m_IsDjnn, m_IsTWJ, m_IsGz);
	}
/***********************************************牌桌进入/退出**********************************************/
	// 进入牌桌
	bool PGChannelInterface::JoinChannel(CharPtr &pChr, bool bSendJoinTown)
	{
		Log.Debug("PGChannelInterface::JoinChannel", "进入牌桌");
		if (pChr.isNull())
			return false;
		WSSocketPtr socket = pChr->getSocket();
		if (socket.isNull())
			return false;
		uint32 pid = 0;
		UserPtr pUser = sUserMgr.getByHandle(pChr->getUInt32Field("userid"));
		if (!pUser.isNull())
			pid = pUser->getUInt32Field("platform_id");
		//bool returnOnece = false;

		WorldPacket packet;

		WGS_CHANNEL_LOCK

		if (m_curState == en_ChannelState_GameOver)
			return false;
		if (sProtocolsMgr.CreateCharacterInfoPacket(&packet, pChr))
			socket->SendPacket(&packet);
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		if (NULL == pTp)
		{
			for (uint32 i = 0; i < PlayerPos.size(); ++i)
			{
				if (PlayerPos[i].player.isNull()) //新加入的玩家
				{
					stCenterBattlePlayerInfo myInfo = sCenterBattleMgr.GetPlayerInfo(m_btLog.cb_id, pChr->getHandle());

					pTp = &PlayerPos[i];
					pTp->player = pChr;
					pTp->pos = i;
					(*pTp).status = en_PlayStatus_Idle;
					//pTp->curScore = myInfo.winLose; // 当前积分
					pTp->curScore = 0; // 当前积分
					if (pid == m_nFzPid)
						(*pTp).bFz = true;
					Log.Debug("PGChannelInterface::JoinChannel", "char[%u] pos[%u]", pChr->getHandle(), (*pTp).pos);
					PGCreatureInterface *pChrAiInfe = TO_CREATURE_INTERFACE(pChr->getAIInterface());
					if (pChrAiInfe)
					{
						pChrAiInfe->SetTown(ResourceProxy(m_pTown));
						pChrAiInfe->SetChannel(ResourceProxy(m_Unit));
					}
					if (sProtocolsMgr.CreatePlayerListPacket(&packet, PlayerPos))
					{
						// Log.Debug("PGProtocolsManager::CreatePlayerListPacket", "发送玩家信息0");
						printf("CreatePlayerListPacket 1 次调用\n");
						BroadcastPacketBC(&packet);
					}
					if (sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, m_strPlayJsonDataCommon))
					{
						printf("CreateCenterBattleInfoPacket 1 次调用\n");
						sGLMgr.SendProtocolsToChr(pChr, &packet);
					}
					

					if (bSendJoinTown)
					{
						if (sProtocolsMgr.CreateEnterTownPacket(&packet, m_pTown->getHandle(), 1))
							sGLMgr.SendProtocolsToChr(pChr, &packet);

						// 发送牌桌信息（用新的棋牌圈玩家列表信息）
						if (sProtocolsMgr.CreatePlayerListPacket(&packet, PlayerPos))
						{
							// Log.Debug("PGProtocolsManager::CreatePlayerListPacket", "发送玩家信息1");
							printf("CreatePlayerListPacket 2 次调用\n");
							BroadcastPacketBC(&packet);
						}

						if (sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, m_strPlayJsonDataCommon))
						{
							printf("CreateCenterBattleInfoPacket 2 次调用\n");
							sGLMgr.SendProtocolsToChr(pChr, &packet);
						}
					}

					Log.Notice("JoinChannel", "channel[%u] char[%u] first joinchannel!", m_Unit->getHandle(), pChr->getHandle());
					break;
				}
			}
		}
		else
		{
			if (bSendJoinTown)
			{
				// 发送牌桌信息（用新的棋牌圈玩家列表信息）
				if (sProtocolsMgr.CreatePlayerListPacket(&packet, PlayerPos))
				{
					printf("CreatePlayerListPacket 3 次调用\n");
					BroadcastPacketBC(&packet);
				}

				if (sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, m_strPlayJsonDataCommon))
				{
					printf("CreateCenterBattleInfoPacket 3 次调用\n");
					sGLMgr.SendProtocolsToChr(pChr, &packet);
				}

				Log.Notice("JoinChannel", "channel[%u] char[%u] second joinchannel!", m_Unit->getHandle(), pChr->getHandle());
			}

			pTp->isOffLine = false;
			pTp->isLeave = false;
		}

		ReturnRoom(pTp);
		return true;
	}	
	//退出游戏
	bool PGChannelInterface::ExitChannel(CharPtr &pChr, bool bOffline, bool bLock)
	{
		WGS_CHANNEL_LOCK

		if (pChr.isNull())
			return false;
		if (pChr->getUInt32Field("status") & CharacterStatusWar)
		{ // 玩家在游戏中不能退出
			TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
			if (pTp)
				pTp->isLeave = true;

			return false;
		}

		bool bRemoveChar = false;

		uint32 char_id = pChr->getHandle();
		std::vector<TablePlayer>::iterator itSeat, eiSeat = PlayerPos.end();
		for (itSeat = PlayerPos.begin(); itSeat != eiSeat; ++itSeat)
		{
			if ((*itSeat).player.isNull())
				continue;

			if (char_id == (*itSeat).player._handle)
			{
				Log.Debug(" PGChannelInterface::ExitChannel", "111111111");
				bRemoveChar = true;

				(*itSeat).Init();
				(*itSeat).InitPlayer();
				break;
			}
		}
		Log.Debug(" PGChannelInterface::ExitChannel", "222222");
		if (bRemoveChar)
		{
			// 调用接口清除角色列表数据
			sCenterBattleMgr.PlayerLeaveChannel(m_btLog.cb_id, pChr->getHandle());

			pChr->setStatus(CharacterStatusFree);

			PGCreatureInterface *pChrAI = TO_CREATURE_INTERFACE(pChr->getAIInterface());
			//离开房间
			pChrAI->SetTownNull();
			pChrAI->SetChannelNull();

			WorldPacket packet;
			if (sProtocolsMgr.CreatePlayerListPacket(&packet, PlayerPos))
			{
				//printf("CreatePlayerListPacket 5 次调用\n");
				BroadcastPacketBC(&packet);
			}
		}
		return true;
	}


/************************************************状态机相关************************************************/
		HSMStateHandler	PGChannelInterface::ChangeChannelState(ChannelState state)
		{
			m_curState = state;
			ResetData();
			switch (m_curState)
			{
				case en_ChannelState_Prepare:
					return HSMStateHandler(PGChannelInterface::channel_prepare);		//准备状态
				case en_ChannelState_RobBanker:
					return HSMStateHandler(PGChannelInterface::channel_Rob_Banker); 	//抢庄定庄状态
				case en_ChannleState_Shuffle:
					return HSMStateHandler(PGChannelInterface::channel_shuffle_cards);  //洗牌状态 
				case en_ChannelState_CutThrowDice:
					return HSMStateHandler(PGChannelInterface::channel_cutthrow_dice);  //丢骰子切牌状态
				case en_ChannelState_Cut:
					return HSMStateHandler(PGChannelInterface::channel_cut_cards); 		//切牌状态
				case en_ChannelState_ChipIn:
					return HSMStateHandler(PGChannelInterface::channel_chip_in); 		//下注状态
				case en_ChannelState_DealThrowDice:
					return HSMStateHandler(PGChannelInterface::channel_dealthrow_dice); //丢骰子发牌状态
				case en_ChannelState_Deal:
					return HSMStateHandler(PGChannelInterface::channel_deal_cards); 	//发牌状态
				case en_ChannelState_Move:
					return HSMStateHandler(PGChannelInterface::channel_move_cards); 	//摆牌状态
				case en_ChannelState_LookCards:
					return HSMStateHandler(PGChannelInterface::channel_look_cards);		//看牌状态
				case en_ChannelState_CalcWait:
					return HSMStateHandler(PGChannelInterface::channel_calc_wait);		//结算状态
				case en_ChannelState_GameOver:
					return HSMStateHandler(PGChannelInterface::channel_game_over);     //游戏结束状态
				case en_ChannelState_ShowTime:
					return HSMStateHandler(PGChannelInterface::channel_show_time); //游戏动画播放
				default:
					return 0;
			}
		}
		//================================动画播放=====================================
		HSMState PGChannelInterface::channel_show_time(PGChannelInterface *me, HSMEvent const *e)
		{
			switch (e->sig)
			{
			case HSM_INIT_SIG:
				me->InitShowTime();
				return HSM_HANDLED();
			case HSM_UPDATE_SIG:
				VCALL(ShowTimeUpdate)
				return HSM_HANDLED();
			}
			return HSM_SUPER(&Hsm::hsm_top);
		}
		//-----------------------------------------------------------------------
		void PGChannelInterface::InitShowTime()
		{
			Log.Debug("PGChannelInterface::InitShowTime", "播放动画！！！");

			m_beginShowTime = now();
		}
		//-----------------------------------------------------------------------
		HSMStateHandler PGChannelInterface::ShowTimeUpdate()
		{

			if (now() - m_beginShowTime >= sXmlDataMgr.GetConfXMLValue("SHOWTIME")) //播放动画时间
			{
				// 其他情况，直接设定状态，进入下一个状态
				if (!m_CardIsEmpty && m_nLoopId > 1)
				{ //还有牌并且不是第一局 直接下注
					return ChangeChannelState(en_ChannelState_ChipIn);
				}
				else
				{ // 没有牌了或者是第一局 重新洗牌
					return ChangeChannelState(en_ChannleState_Shuffle);
				}
			}

			return 0;
		}
		//-----------------------------------------------------------------------
		HSMState PGChannelInterface::channel_init(PGChannelInterface *me, HSMEvent const *e)
		{
			return HSM_TRAN(&PGChannelInterface::channel_prepare);
		}
		//-----------------------------------------------------------------------
		HSMState PGChannelInterface::channel_prepare(PGChannelInterface *me, HSMEvent const *e)
		{
			switch(e->sig)
			{
				case HSM_INIT_SIG:
					me->InitPrepareState();				
					return HSM_HANDLED();
				case HSM_UPDATE_SIG:
					VCALL(PrepareUpdate)
					return HSM_HANDLED();
			}
			return HSM_SUPER(&Hsm::hsm_top);
		}
		//-----------------------------------------------------------------------
		void PGChannelInterface::InitPrepareState()
		{
			Log.Update("PGChannelInterface::InitPrepareState", ">>>>>chn[%u] begin initprepare[%u] state!!!", m_Unit->getHandle(), m_curState);
			m_beginWaitTime = now();
		}
		//-----------------------------------------------------------------------
		HSMStateHandler	PGChannelInterface::PrepareUpdate()
		{
			WGS_CHANNEL_LOCK

			if (m_curState == en_ChannelState_GameOver && m_nLoopId == 0)
			{
				return ChangeChannelState(en_ChannelState_GameOver);
			}

			if (!CheckPlayersCanStatPlayGame())
			{ // 先检测最少人数是否能开
				return 0;
			}
			if (CheckGameStart())
			{ // 达到游戏开始条件
				Log.Warning("PGChannelInterface::PrepareUpdate", "都已准备，即将开始游戏。。。。");
				return ChangeChannelState(en_ChannelState_RobBanker);
			}
			return 0;
		}
		//================================抢庄定庄=====================================
		HSMState PGChannelInterface::channel_Rob_Banker(PGChannelInterface *me, HSMEvent const *e)
		{
			switch (e->sig)
			{
			case HSM_INIT_SIG:
				me->InitRobBankerState();
				return HSM_HANDLED();
			case HSM_UPDATE_SIG:
				VCALL(RobBankerUpdate)
				return HSM_HANDLED();
			}
			return HSM_SUPER(&Hsm::hsm_top);
		}
		//-----------------------------------------------------------------------
		void PGChannelInterface::InitRobBankerState()
		{
			WGS_CHANNEL_LOCK

			Log.Update("PGChannelInterface::InitRobBankerState", ">>>>>chn[%u] begin robbanker[%u] state!!!", m_Unit->getHandle(), m_curState);
			WorldPacket packet;
			std::vector<TablePlayer>::iterator iter, ei = PlayerPos.end();
			Log.Warning("PGChannelInterface::InitRobBankerState", "当前进行轮数：%d",m_nLoopId);
			//抢庄和霸王庄游戏结束条件
			if (m_nLoopBankerMode!=en_GameMode_Orderbanker)
			{
				if (m_nLoopId > 1)
				{
					Log.Warning("PGChannelInterface::InitRobBankerState", "抢庄模式当前底分:%d 初始底分:%d ", m_BaseScore, m_nBasePoint); // 霸王庄逻辑
					if (m_changeBanker) //输完底分或到达切锅倍数
						m_bGameOver = true;
				}
			}
			//轮庄游戏结束条件
			else
			{
				if(AllInTurn())
				{
					Log.Warning("PGChannelInterface::InitRobBankerState", "轮庄当前底分:%d 初始底分:%d ", m_BaseScore, m_nBasePoint);
					if (m_changeBanker) //输完底分或到达切锅倍数
						m_bGameOver = true;
				}
				
			}

			//游戏未结束并且第一局之后每局都询问
			if (m_nLoopId > 1 && !m_bGameOver && !m_changeBanker && m_CardIsEmpty)
			{ //询问是否连庄
				if (PlayerPos[m_nBankerPos].onceBanker)
				{
					CharPtr pChr = PlayerPos[m_nBankerPos].player.getResourcePtr();
					if (sProtocolsMgr.CreateAskIsContinueBankerPacket(&packet, sXmlDataMgr.GetConfXMLValue("CT_WT")))
						sGLMgr.SendProtocolsToChr(pChr, &packet);
					Log.Debug("PGChannelInterface::InitRobBankerState", "连庄已选择");
				}
			}
			m_changeBanker = false;
			// 抢庄模式第一局，等待玩家抢庄
			if (m_nLoopBankerMode == en_GameMode_RobBanker && m_nLoopId == 1)
			{
				Log.Warning("PGChannelInterface::RobBankerUpdate", "抢庄模式第一轮：通知所有玩家抢庄");
				if (sProtocolsMgr.CreateNoticeGetBankerPacket(&packet, 0))
					BroadcastPacketBC(&packet);
			}
			//Log.Debug("PGChannelInterface::RobBankerUpdate", "游戏模式:%d", m_nLoopBankerMode);
			m_status_endtimer = now() + sXmlDataMgr.GetConfXMLValue("ST_WT"); //定庄等待时间
			m_status_waitimer = now() + sXmlDataMgr.GetConfXMLValue("CT_WT"); //连庄等待时间
		}
		//-----------------------------------------------------------------------
		HSMStateHandler PGChannelInterface::RobBankerUpdate()
		{
			WorldPacket packet;

			 WGS_CHANNEL_LOCK
			 
			if (m_curState == en_ChannelState_GameOver && m_nLoopId == 1)
			{
				return ChangeChannelState(en_ChannelState_GameOver);
			}
		
			if(m_bGameOver)//结束条件为真
			{
				PlayerPos[m_nBankerPos].curScore += m_BaseScore;
				return ChangeChannelState(en_ChannelState_GameOver);
			}
			

				if (m_nLoopId == 1)
				{
					if (m_nLoopBankerMode == en_GameMode_RobBanker)
					{
						// 抢庄模式第一局，等待玩家抢庄
						if (m_status_endtimer >= now() && m_nOptTimes < PLAYER_NUM)
						{ // 等待时间未到，并且还有玩家未操作，继续等待
							return 0;
						}
					}
					
				}
				else
				{//不是第一局下已选择
					if (m_contOrstop)
					{
						Log.Debug("PGChannelInterface::RobBankerUpdate", "庄家让庄，结束游戏");
						if (m_bankerAnswer == en_AnswerType_Yes)
						{
							if (m_nLoopBankerMode != en_GameMode_Orderbanker)
							{
								m_bGameOver = true;
								PlayerPos[m_nBankerPos].curScore += m_BaseScore;
								return ChangeChannelState(en_ChannelState_GameOver);
							}
							//轮庄
							else
							{
								//每个玩家至少当庄一次并且庄家同意切锅时结束游戏
								if (AllInTurn() && m_bankerAnswer == en_AnswerType_Yes)
								{
									Log.Debug("PGChannelInterface::RobBankerUpdate", "，自动下庄并结束游戏");
									m_bGameOver = true;
									PlayerPos[m_nBankerPos].curScore += m_BaseScore;
									return ChangeChannelState(en_ChannelState_GameOver);
								}
							}
						} 
					
					}
					else
					{
						if (m_CardIsEmpty) //未选择
						{
							if (m_changeBanker && m_nLoopBankerMode == en_GameMode_Orderbanker)
							{
								// 等待时间到 系统设定庄家
								SetBankerPos();
								if (sProtocolsMgr.CreatePlayerListPacket(&packet, PlayerPos))
								{
									printf("CreatePlayerListPacket 7 次调用\n");
									BroadcastPacketBC(&packet);
								}
								Log.Debug("PGChannelInterface::RobBankerUpdate", "en_GameMode_Orderbanker[%d]",en_GameMode_Orderbanker);
								m_changeBanker = false;
								// 其他情况，直接设定状态，进入下一个状态
								// 没有牌了 重新洗牌
								return ChangeChannelState(en_ChannleState_Shuffle);

							}

								return 0;
						}
						//时间到了，默认下庄，结束游戏
						// if (m_status_waitimer < now() && m_nLoopBankerMode != en_GameMode_Orderbanker && m_CardIsEmpty)
						// {
						// 	Log.Debug("PGChannelInterface::RobBankerUpdate", "时间到了，庄家未操作，自动下庄并结束游戏");
						// 	m_bankerAnswer = en_AnswerType_Yes;
						// 	m_bGameOver = true;
						// 	return ChangeChannelState(en_ChannelState_GameOver);
						// }
					}
					
				}

				//Log.Debug("PGChannelInterface::RobBankerUpdate","庄家已选择连庄");
				// 等待时间到 系统设定庄家
				SetBankerPos();
				if (sProtocolsMgr.CreatePlayerListPacket(&packet, PlayerPos))
				{
					//("CreatePlayerListPacket 8 次调用\n");
					BroadcastPacketBC(&packet);
				}
				//抢庄模式第一轮播放动画
				if(m_nLoopId ==1 && m_nLoopBankerMode == en_GameMode_RobBanker)
				{
					return ChangeChannelState(en_ChannelState_ShowTime);
				}
				// 其他情况，直接设定状态，进入下一个状态
				if (!m_CardIsEmpty && m_nLoopId > 1)
				{ //还有牌并且不是第一局 直接下注
					return ChangeChannelState(en_ChannelState_ChipIn);
				}
				else
				{// 没有牌了或者是第一局 重新洗牌
					return ChangeChannelState(en_ChannleState_Shuffle);
				}
			return 0;
		}
		//================================洗牌=====================================
		HSMState PGChannelInterface::channel_shuffle_cards(PGChannelInterface *me, HSMEvent const *e)
		{
			switch (e->sig)
			{
			case HSM_INIT_SIG:
				me->InitShuffleCardState();
				return HSM_HANDLED();
			case HSM_UPDATE_SIG:
				VCALL(ShuffleCardUpdate)
				return HSM_HANDLED();
			}

			return HSM_SUPER(&Hsm::hsm_top);
		}
		//-----------------------------------------------------------------------
		void PGChannelInterface::InitShuffleCardState()
		{
			WGS_CHANNEL_LOCK

			Log.Update("PGChannelInterface::InitShuffleCardState", ">>>>>chn[%u] begin shufflecards[%u] state!!!", m_Unit->getHandle(), m_curState);
			// 通知洗牌
			WorldPacket packet;
			if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState, sXmlDataMgr.GetConfXMLValue("SHFFLECARD")))
				BroadcastPacketBC(&packet);
				m_vecCurCards.clear();
				// 洗牌
				PaiGowType brand_value[TYPENUM] = {
														/* @Number 	@Points @IsRed  @IsTwo */
					{2, true, true},{2, true, true},     /* 2		2		yes		yes	   */
					{3, true, false}, 					 /*	1		3		yes		no	   */
					{4, true, true},{4, true, true}, 	 /*	2		4		yes		yes	   */
					{4, false, true},{4, false, true},   /*	2		4		no		yes	   */
					{5, true, false}, 					 /*	1		5		yes		no	   */
					{5, false, false},					 /*	1		5		no		no	   */
					{6, false, true},{6, false, true},   /*	2		6		no		yes	   */
					{6, true, true},{6, true, true},     /*	2		6		yes		yes	   */
					{6, true, false}, 					 /*	1		6		yes		no	   */
					{7, true, false}, 					 /*	1		7		yes		no	   */
					{7, false, false},					 /*	1		7		no		no	   */
					{7, true, true},{7, true, true},   	 /*	2		7		yes		yes	   */
					{8, true, true},{8, true, true},     /*	2		8		yes		yes	   */
					{8, false, false}, 					 /*	1		8		no		no	   */
					{8, true, false}, 				     /*	1		8		yes		no	  平八 */
					{9, true, false},  					 /*	1		9		yes		no	   */
					{9, false, false}, 					 /*	1		9		no		no	   */
					{10, true, true},{10, true, true},   /*	2		10		yes		yes	   */
					{10, false, true},{10, false, true}, /*	2		10		no		yes	   */
					{11, false, true},{11, false, true}, /*	2		11		no		yes	   */
					{12, true, true},{12, true, true}, 	 /*	2		12		yes		yes	   */
				};										 /* 32							   */

				for (int i = 0; i < TYPENUM; ++i)
					m_vecCurCards.push_back(brand_value[i]);
				//ShuffleText();//指定牌
				uint32 num = RandomUInt(sXmlDataMgr.GetConfXMLValue("RIFFLE_MIN"), sXmlDataMgr.GetConfXMLValue("RIFFLE_MAX"));
				std::vector<PaiGowType> tempVec;
				while (num-- > 0)
				{
					tempVec = m_vecCurCards;
					m_vecCurCards.clear();
					while (tempVec.size() > 0)
					{
						uint32 pos = RandomUInt(tempVec.size() - 1);
						std::vector<PaiGowType>::iterator iter = tempVec.begin() + pos;
						m_vecCurCards.push_back(*iter);
						tempVec.erase(iter);
					
					}
				}
				m_beginWaitTime = now();
		}

		//-----------------------------------------------------------------------
		HSMStateHandler PGChannelInterface::ShuffleCardUpdate()
		{
			if (m_curState == en_ChannelState_GameOver && m_nLoopId == 1)
			{
				return ChangeChannelState(en_ChannelState_GameOver);
			}
			if (now() - m_beginWaitTime >= sXmlDataMgr.GetConfXMLValue("SHFFLECARD")) //洗牌播放动画时间
			{
				return ChangeChannelState(en_ChannelState_CutThrowDice);
			}
			return 0;
		}
		//===========================丢骰子决定切牌位置=============================
		HSMState PGChannelInterface::channel_cutthrow_dice(PGChannelInterface *me, HSMEvent const *e)
		{
			switch (e->sig)
			{
			case HSM_INIT_SIG:
				me->InitCutThrowDiceState();
				return HSM_HANDLED();
			case HSM_UPDATE_SIG:
				VCALL(CutThrowDiceUpdate)
				return HSM_HANDLED();
			}
			return HSM_SUPER(&Hsm::hsm_top);
		}
		//-----------------------------------------------------------------------
		void PGChannelInterface::InitCutThrowDiceState()
		{
			Log.Update("PGChannelInterface::InitThrowDiceState", ">>>>>chn[%u] begin throwdicecut[%u] state!!!", m_Unit->getHandle(), m_curState);
			// 通知丢骰子
			WorldPacket packet;
			if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState, sXmlDataMgr.GetConfXMLValue("THROWDICETIME")))
				BroadcastPacketBC(&packet);
			m_beginWaitTime = now();
		
			// 丢骰子
			srand(time(0));
			m_dices1 = RandomUInt(1, 6);
			m_dices2 = RandomUInt(1, 6);
			m_dices = (m_dices1 + m_dices2) % PLAYER_NUM;

			std::vector<TablePlayer>::iterator iter = PlayerPos.begin();
			for (uint32 ix = 0; ix < 1; ++ix)
				++iter;
			uint32 cutId = (*iter).player._handle;
			m_nSpeakPos = (*iter).pos;
			// 下发骰子点数
			if (sProtocolsMgr.CreateBroadcastDiceResultPacket(&packet, m_dices1, m_dices2, m_nSpeakPos, cutId))
				BroadcastPacketBC(&packet);
			//Log.Debug("PGChannelInterface::InitThrowDiceState", "dices1:%d dices2:%d ", m_dices1, m_dices2);
			m_beginWaitTime = now();
		}
		//-----------------------------------------------------------------------
		HSMStateHandler	PGChannelInterface::CutThrowDiceUpdate()
		{
			if (now() - m_beginWaitTime >= sXmlDataMgr.GetConfXMLValue("THROWDICETIME")) //切牌掷骰子播放动画时间
			{
				return ChangeChannelState(en_ChannelState_Cut);
			}
			
			return 0;
		}
		//==================================切牌====================================
		HSMState PGChannelInterface::channel_cut_cards(PGChannelInterface *me, HSMEvent const *e)
		{
			switch (e->sig)
			{
			case HSM_INIT_SIG:
				me->InitCutCardInState();
				return HSM_HANDLED();
			case HSM_UPDATE_SIG:
				VCALL(CutCardInUpdate)
				return HSM_HANDLED();
			}

			return HSM_SUPER(&Hsm::hsm_top);
		}

		//-----------------------------------------------------------------------
		void PGChannelInterface::InitCutCardInState()
		{
			Log.Update("PGChannelInterface::InitCutCardInState", ">>>>>chn[%u] begin cutcards[%u] state!!!", m_Unit->getHandle(), m_curState);
			// 通知切牌
			WorldPacket packet;
			if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState, sXmlDataMgr.GetConfXMLValue("CUTCARDSTIME")))
				BroadcastPacketBC(&packet);
			m_beginWaitTime = sXmlDataMgr.GetConfXMLValue("CUTCARDSTIME"); //切牌等待时间;
			m_lastSaveTime = now();
		}
		//-----------------------------------------------------------------------
		HSMStateHandler PGChannelInterface::CutCardInUpdate()
		{
			WGS_CHANNEL_LOCK

			WorldPacket packet;
			if (m_curState == en_ChannelState_GameOver && m_nLoopId == 1)
			{
				return ChangeChannelState(en_ChannelState_GameOver);
			}

			if (m_curState == en_ChannelState_ChipIn)
			{// 玩家操作结束，标记要切换的状态达成，切换状态
				return ChangeChannelState(en_ChannelState_ChipIn);
			}

			if (now() - m_lastSaveTime < m_beginWaitTime && PlayerPos[m_nSpeakPos].cutresult != en_CutCards_No && PlayerPos[m_nSpeakPos].cutcardfinsh != true)
			{
				// 时间未到
				return 0;
			}
			
			// 等待时间结束或玩家不选择切牌，切换下一个玩家
			m_lastSaveTime = now();
			TablePlayer tp = PlayerPos[m_nSpeakPos];
			tp.cutcardflag = true;

			++m_cutplayer;
			if (m_cutplayer >= PLAYER_NUM)
			{// 所有玩家都已经操作
				m_curState = en_ChannelState_ChipIn;
			}
			else
			{// 还有玩家没有操作，通知下一个玩家
				m_nSpeakPos = (m_nSpeakPos + 1) % PLAYER_NUM;
				if (sProtocolsMgr.CreateBroadCutResultPacket(&packet, PlayerPos[m_nSpeakPos], m_nSpeakPos, m_cutplayer, sXmlDataMgr.GetConfXMLValue("CUTCARDSTIME"), false))
					BroadcastPacketBC(&packet);
			}
			return 0;
		}
		//==================================下注====================================
		HSMState PGChannelInterface::channel_chip_in(PGChannelInterface *me, HSMEvent const *e)
		{
			switch (e->sig)
			{
			case HSM_INIT_SIG:
				me->InitChipInState();
				return HSM_HANDLED();
			case HSM_UPDATE_SIG:
				VCALL(ChipInUpdate)
				return HSM_HANDLED();
			}

			return HSM_SUPER(&Hsm::hsm_top);
		}

		//-----------------------------------------------------------------------
		void PGChannelInterface::InitChipInState()
		{
			Log.Update("PGChannelInterface::InitChipInState", ">>>>>chn[%u] begin dicechin[%u] state!!!", m_Unit->getHandle(), m_curState);

			for (size_t i = 0; i < PlayerPos.size(); ++i)
			{
				PlayerPos[i].surplusScore = m_BaseScore;
			}
			WorldPacket packet;
			if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState, sXmlDataMgr.GetConfXMLValue("CHIPINTIME")))
				BroadcastPacketBC(&packet);
			m_beginWaitTime = now();
		}
		//-----------------------------------------------------------------------
		HSMStateHandler PGChannelInterface::ChipInUpdate()
		{
			WGS_CHANNEL_LOCK

			WorldPacket packet;
			uint8 chinNum = 0;
			if (m_curState == en_ChannelState_GameOver)
			{
				return ChangeChannelState(en_ChannelState_GameOver);
			}
			std::vector<TablePlayer>::iterator iter = PlayerPos.begin();
			for (; iter != PlayerPos.end(); ++iter)
			{
				if ((*iter).isChin && (*iter).pos != m_nBankerPos)
					++chinNum;
	
			}

			if (chinNum == 3)
				return ChangeChannelState(en_ChannelState_DealThrowDice);

			// if (now() - m_beginWaitTime >= sXmlDataMgr.GetConfXMLValue("CHIPINTIME")) //下注播放动画时间
			// {
			// 	std::vector<TablePlayer>::iterator iter1 = PlayerPos.begin();
			// 	for (; iter1 != PlayerPos.end(); ++iter1)
			// 	{
			// 		if (!(*iter1).isChin && (*iter1).pos != m_nBankerPos)
			// 		{
			// 			(*iter1).mapNumScore[1] = 0.1 * m_BaseScore;
			// 			(*iter1).mapNumScore[2] = 0;
			// 			(*iter1).mapNumScore[3] = 0;
			// 			Log.Debug("PGChannelInterface::ChipInUpdate", "score1:%d score2:%d score3:%d ", 
			// 			(*iter1).mapNumScore[1], (*iter1).mapNumScore[2], (*iter1).mapNumScore[3]);

			// 			if (sProtocolsMgr.CreateChipInResultPacket(&packet, 1, (*iter1).mapNumScore, (*iter1).pos))
			// 				BroadcastPacketBC(&packet);
			// 		}
	
			// 	}
			// 	return ChangeChannelState(en_ChannelState_DealThrowDice);
			// }
			
			return 0;
		}
		//===========================丢骰子决定发牌位置状态=======================
		HSMState PGChannelInterface::channel_dealthrow_dice(PGChannelInterface *me, HSMEvent const *e)
		{
			switch (e->sig)
			{
			case HSM_INIT_SIG:
				me->InitDealThrowDiceState();
				return HSM_HANDLED();
			case HSM_UPDATE_SIG:
				VCALL(DealThrowDiceUpdate)
				return HSM_HANDLED();
			}
			return HSM_SUPER(&Hsm::hsm_top);
		}
		//-----------------------------------------------------------------------
		void PGChannelInterface::InitDealThrowDiceState()
		{
			Log.Update("PGChannelInterface::InitThrowDiceState", ">>>>>chn[%u] begin throwdicedeal[%u] state!!!", m_Unit->getHandle(), m_curState);
			// 通知丢骰子
			WorldPacket packet;
			if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState, sXmlDataMgr.GetConfXMLValue("THROWDICETIME")))
				BroadcastPacketBC(&packet);
			m_beginWaitTime = time(0);
			uint32 m_dices;
		
			// 丢骰子
				srand(time(0));
				m_dices1 = RandomUInt(1, 6);
				m_dices2 = RandomUInt(1, 6);
			m_dices = (m_dices1 + m_dices2) % PLAYER_NUM;

			std::vector<TablePlayer>::iterator iter1 = PlayerPos.begin();
			for (uint32 ix = 0; ix < m_dices; ++ix)
				++iter1;
			uint32 cutId = (*iter1).player._handle;
			m_nSpeakPos = (*iter1).pos;
			// 下发骰子点数
			if (sProtocolsMgr.CreateBroadcastDiceResultPacket(&packet, m_dices1, m_dices2, m_nSpeakPos, cutId))
				BroadcastPacketBC(&packet);
				// 等待播动画
				m_beginWaitTime = now();
		}
		//-----------------------------------------------------------------------
		HSMStateHandler PGChannelInterface::DealThrowDiceUpdate()
		{

			if (now() - m_beginWaitTime >= sXmlDataMgr.GetConfXMLValue("THROWDICETIME")) //等待播放丢骰子画面
			{
				return ChangeChannelState(en_ChannelState_Deal);
				} 
			return 0;
		}
		//================================发牌======================================
		HSMState PGChannelInterface::channel_deal_cards(PGChannelInterface *me, HSMEvent const *e)
		{
			switch (e->sig)
			{
			case HSM_INIT_SIG:
				me->InitDealState();
				return HSM_HANDLED();
			case HSM_UPDATE_SIG:
				VCALL(DealUpdate)
				return HSM_HANDLED();
			}

			return HSM_SUPER(&Hsm::hsm_top);
		}
		//-----------------------------------------------------------------------
		void PGChannelInterface::InitDealState()
		{
			WGS_CHANNEL_LOCK

			Log.Update("PGChannelInterface::InitDealState", ">>>>>chn[%u] begin Deal[%u] state!!!", m_Unit->getHandle(), m_curState);
			// 通知发牌
			WorldPacket packet;
			if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState, sXmlDataMgr.GetConfXMLValue("DEAL_TIME")))
				BroadcastPacketBC(&packet);
			m_beginWaitTime = now();
			uint8 result;
			// 发牌
			for (size_t i = 0; i < PlayerPos.size(); ++i)
			{
				for (uint32 j = 0; j < PLAYER_NUM; ++j)
				{
					uint8 rand_index = RandomUInt(0, m_vecCurCards.size() - 1);
					std::vector<PaiGowType>::iterator iter = m_vecCurCards.begin()+rand_index;
					PlayerPos[i].cards.InsertCard(*iter, m_specialtype);
					PlayerPos[i].Originalcards = PlayerPos[i].cards;
					m_vecCurCards.erase(iter);
				}
				//测试牌
				//ShuffleText(i);

				Log.Debug("PGChannelInterface::InitDealState", "给玩家%d发牌 牌点数< (%d %d %d),(%d %d %d),(%d %d %d),(%d %d %d) >", PlayerPos[i].pos
				,PlayerPos[i].cards.vecCards[0].point,PlayerPos[i].cards.vecCards[0].color,PlayerPos[i].cards.vecCards[0].two
				,PlayerPos[i].cards.vecCards[1].point,PlayerPos[i].cards.vecCards[1].color,PlayerPos[i].cards.vecCards[1].two
				,PlayerPos[i].cards.vecCards[2].point,PlayerPos[i].cards.vecCards[2].color,PlayerPos[i].cards.vecCards[2].two
				,PlayerPos[i].cards.vecCards[3].point,PlayerPos[i].cards.vecCards[3].color,PlayerPos[i].cards.vecCards[3].two);
				//发送每个玩家的牌信息
				CharPtr pChr = PlayerPos[i].player.getResourcePtr();
				//一二组比牌结果
				SelfCardsTypeCheck(PlayerPos[i].cards,0, 0,result);

				if (sProtocolsMgr.CreatePlayerLookCardTypePacket(&packet, result, PlayerPos[i]))
					sGLMgr.SendProtocolsToChr(pChr, &packet);
			}
			if(m_vecCurCards.empty())
				m_CardIsEmpty = true;
		}
		//-----------------------------------------------------------------------
		HSMStateHandler PGChannelInterface::DealUpdate()
		{
			if (m_curState == en_ChannelState_GameOver && m_nLoopId == 1)
			{
				return ChangeChannelState(en_ChannelState_GameOver);
			}
			if (now() - m_beginWaitTime >= sXmlDataMgr.GetConfXMLValue("DEAL_TIME")) //发牌播放动画时间
			{
				return ChangeChannelState(en_ChannelState_Move);
			}
			return 0;
		}
		//===============================摆牌===================================
		HSMState PGChannelInterface::channel_move_cards(PGChannelInterface *me, HSMEvent const *e)
		{
			switch (e->sig)
			{
			case HSM_INIT_SIG:
				me->InitMoveCardsState();
				return HSM_HANDLED();
			case HSM_UPDATE_SIG:
				VCALL(MoveCardsUpdate)
				return HSM_HANDLED();
			}

			return HSM_SUPER(&Hsm::hsm_top);
		}
		//-----------------------------------------------------------------------
		void PGChannelInterface::InitMoveCardsState()
		{
			Log.Update("PGChannelInterface::InitMoveCardsState", ">>>>>chn[%u] begin move[%u] state!!!", m_Unit->getHandle(), m_curState);
			//通知摆牌
			WorldPacket packet;
			if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState, sXmlDataMgr.GetConfXMLValue("MOVE_TIME")))
				BroadcastPacketBC(&packet);			
			m_lastSaveTime = 1; // 标记已通知看牌
			m_beginWaitTime = now();
		}
		//-----------------------------------------------------------------------
		HSMStateHandler PGChannelInterface::MoveCardsUpdate()
		{
			WGS_CHANNEL_LOCK

			uint8 moveNum =0;
			if (m_curState == en_ChannelState_GameOver && m_nLoopId == 1)
			{
				return ChangeChannelState(en_ChannelState_GameOver);
			}

			std::vector<TablePlayer>::iterator iter = PlayerPos.begin();
			for (; iter != PlayerPos.end(); ++iter)
			{
				if ((*iter).IsMovefinish)
					++moveNum;
			}

			if (moveNum == PLAYER_NUM)
				return ChangeChannelState(en_ChannelState_LookCards);

			// if (now() - m_beginWaitTime >= sXmlDataMgr.GetConfXMLValue("MOVE_TIME"))
			// {//检测玩家最终牌型是否满足要求
			// 	uint8 result;
			// 	std::vector<TablePlayer>::iterator iter = PlayerPos.begin();
			// 	for (; iter != PlayerPos.end(); ++iter)
			// 	{
			// 		if (!(*iter).IsMovecard || !(*iter).IsMovefinish)
			// 		{
			// 			//Log.Debug("PGChannelInterface::MoveCardsUpdate", "玩家%d ", (*iter).pos);
			// 			if ((*iter).IsMovecard)
			// 			{
			// 				if ((*iter).movecardresult == en_PGCompareResult_Greater)
			// 					(*iter).cards = SystemProcessCardsType(*iter);
			// 			}
			// 			else 
			// 			{
			// 				SelfCardsTypeCheck((*iter).cards, 0, 0, result);
			// 				if (result == en_PGCompareResult_Greater)
			// 					(*iter).cards = SystemProcessCardsType(*iter);
			// 			}
			// 		}
			// 	}
			// 	return ChangeChannelState(en_ChannelState_LookCards);
			// }
			return 0;
		}
		//=================================看牌======================================
		HSMState PGChannelInterface::channel_look_cards(PGChannelInterface *me, HSMEvent const *e)
		{
			switch(e->sig)
			{
				case HSM_INIT_SIG:
					me->InitLookCardsState();
					return HSM_HANDLED();
				case HSM_UPDATE_SIG:
					VCALL(LookCardsUpdate)
					return HSM_HANDLED();
			}
			
			return HSM_SUPER(&Hsm::hsm_top);
		}
		//-----------------------------------------------------------------------
		void PGChannelInterface::InitLookCardsState()
		{
			Log.Update("PGChannelInterface::InitLookCardsState", ">>>>>chn[%u] begin look[%u] state!!!", m_Unit->getHandle(), m_curState);
			// 通知看牌
			WorldPacket packet;
			if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState, sXmlDataMgr.GetConfXMLValue("LOOK_TIME")))
				BroadcastPacketBC(&packet);
			Log.Debug("PGChannelInterface::InitLookCardsState","庄家看牌================");

			CharPtr pChr = PlayerPos[m_nBankerPos].player.getResourcePtr();
			// 下发各个方位牌信息
			if (sProtocolsMgr.CreateBankerLookCardsPacket(&packet, PlayerPos))
					BroadcastPacketBC(&packet);
			m_lastSaveTime = 1; // 标记已通知看牌
			m_beginWaitTime = now();
		}
		//-----------------------------------------------------------------------
		HSMStateHandler	PGChannelInterface::LookCardsUpdate()
		{
			WGS_CHANNEL_LOCK

			uint8 lookNum =0; 
			if (m_curState == en_ChannelState_GameOver && m_nLoopId == 1)
			{
				return ChangeChannelState(en_ChannelState_GameOver);
			}
			std::vector<TablePlayer>::iterator iter = PlayerPos.begin();
				for (; iter != PlayerPos.end(); ++iter)
				{
					if ((*iter).IsLookcard)
						++lookNum;
				}
				if (lookNum == PLAYER_NUM)
					return ChangeChannelState(en_ChannelState_CalcWait);

			if (now() - m_beginWaitTime >= sXmlDataMgr.GetConfXMLValue("LOOK_TIME"))
			{
				return ChangeChannelState(en_ChannelState_CalcWait);
			}
			return 0;
		}
		//=================================结算======================================
		HSMState PGChannelInterface::channel_calc_wait(PGChannelInterface *me, HSMEvent const *e)
		{
			switch(e->sig)
			{
				case HSM_INIT_SIG:
					me->InitCalcWaitState();
					return HSM_HANDLED();
				case HSM_UPDATE_SIG:
					VCALL(CalcWaitUpdate)
					return HSM_HANDLED();
			}
			
			return HSM_SUPER(&Hsm::hsm_top);
		}
		//-----------------------------------------------------------------------
		void PGChannelInterface::InitCalcWaitState()
		{
			WGS_CHANNEL_LOCK

			int baseScore;
			Log.Update("PGChannelInterface::InitGameOverState", ">>>>>chn[%u] begin gameover[%u] state!!!", m_Unit->getHandle(), m_curState);
			// 统计结果
			WorldPacket packet;
			//积分以及赛果计算
			CalcScoreResult();
			//游戏数据记录
			CalcGameResultLog();
			Log.Debug("PGChannelInterface::InitCalcWaitState", " 当前分:%d  锅底：%d 封顶倍数：%d", m_BaseScore, m_nBasePoint, m_nTopTimes);

			if (!m_bGameOver)
			{
				if (m_BaseScore <= 0 || ((m_BaseScore / m_nBasePoint) >= m_nTopTimes))
				{
					baseScore = m_nBasePoint;
					m_changeBanker = true;
					Log.Warning("PGChannelInterface::InitCalcWaitState", "m_changeBanker[%d]", m_changeBanker);
				}
				else
					baseScore = m_BaseScore;
			}
			//每局结算
			if (sProtocolsMgr.CreateRoundPGCalcPacket(&packet, PlayerPos, m_nBankerPos, m_rType, baseScore, true))
				BroadcastPacketBC(&packet);
			Log.Warning("PGChannelInterface::InitCalcWaitState", "发送每局结算。。。");
			SendCenterBattleInfo(m_BaseScore);

			m_beginWaitTime = now();
		}
		
		//-----------------------------------------------------------------------
		HSMStateHandler PGChannelInterface::CalcWaitUpdate()
		{
			WGS_CHANNEL_LOCK

			WorldPacket packet;
			uint32 interval = sXmlDataMgr.GetConfXMLValue("GAMEOVER_TIME");
			uint32 oncesendtime = sXmlDataMgr.GetConfXMLValue("SENDTIME");

			if (m_curState == en_ChannelState_GameOver && m_nLoopId == 1)
			{
				return ChangeChannelState(en_ChannelState_GameOver);
			}
			if (now() - m_beginWaitTime >= oncesendtime && !m_nOnceSend)
			{
				if (sProtocolsMgr.CreatePlayerListPacket(&packet, PlayerPos))
				{
					//printf("CreatePlayerListPacket 6 次调用\n");
					BroadcastPacketBC(&packet);
				}
				m_nOnceSend = true;
			}


			if (now() - m_beginWaitTime >= interval && m_bIsAllCalc)
			{
				if(m_bGameOver) 
					return ChangeChannelState(en_ChannelState_GameOver);

				else
				{
					// 重置本轮数据
					initialize();
					// 重置方位数据
					for (size_t i = 0; i < PlayerPos.size(); ++i)
					{
						PlayerPos[i].Init();
					}
					if (!m_vecCurCards.empty())
						m_CardIsEmpty = false;

					Log.Warning("PGChannelInterface::GameOverUpdate", "本轮游戏结束，即将开始下一轮。。。");
					return ChangeChannelState(en_ChannelState_Prepare);
				}
			}
			return 0;
		}
		//=================================游戏结束======================================
		HSMState PGChannelInterface::channel_game_over(PGChannelInterface *me, HSMEvent const *e)
		{
			switch (e->sig)
			{
			case HSM_INIT_SIG:
				me->InitGameOverState();
				return HSM_HANDLED();
			}

			return HSM_SUPER(&Hsm::hsm_top);
		}
		//-----------------------------------------------------------------------
		void PGChannelInterface::InitGameOverState()
		{
			WGS_CHANNEL_LOCK

			WorldPacket packet;
			//游戏正常结束
			uint8 reson = enCenterBattleReturnGold_Normal; // 正常结束
				// 解散时候 为结算过，需要返还房费
				if(m_nDissolveReson == 0)
					m_nDissolveReson = DissolveType_Loop;
				if (m_nDissolveReson == DissolveType_Vote && !m_bFinishCalc)
				{
					reson = enCenterBattleReturnGold_OwnerDissolve; // 解散
				}

				if (m_nDissolveReson == DissolveType_Homeowners && !m_bFinishCalc)
				{
					reson = enCenterBattleReturnGold_OwnerDissolve; // 解散
				}

			if (sProtocolsMgr.CreateDissolveChannelPacket(&packet, m_nDissolveReson))
				BroadcastPacketBC(&packet);
			//游戏结束断线不再重连	
			std::vector<TablePlayer>::iterator itPlayer, eiPlayer = PlayerPos.end();
			for (itPlayer = PlayerPos.begin(); itPlayer != eiPlayer; ++itPlayer)
			{
				if ((*itPlayer).player.isNull())
					continue;

				(*itPlayer).nAgreeSameIp = enAgreeOrRefuse_None;

				// 设置角色战斗状态
				CharPtr pChr = sCharMgr.load((*itPlayer).player._handle);
				pChr->setStatus(CharacterStatusFree);
			}
			sCenterBattleMgr.CenterBattleComplate(m_btLog.cb_id, reson); // 组局结束
			// 所有玩家离开牌桌
			AllPlayersLeaveRoom();
			((Channel *)m_Unit)->setWantRemove(); //关掉线程，退出状态
			Log.Debug("PGChannelInterface::GameOverUpdate", "游戏结束，解散牌桌。。。");
		}


/***********************************************游戏功能函数***********************************************/

	//结算积分结果
	void PGChannelInterface::CalcScoreResult()
	{
		m_lstOutCards.clear();
		uint32 winCount = 0; // 庄家赢次数
		Cards bankerCards;
		std::vector<TablePlayer>::iterator iter = PlayerPos.begin();
		for (; iter != PlayerPos.end(); ++iter)
		{
			if ((*iter).pos == m_nBankerPos)
				bankerCards = (*iter).cards;
		}
		// 本轮庄家输赢的钱
		int bankerWinScore = 0;
		int bankerLossScore = 0;
		int finishWinScore = 0;

		stIncomeInfo stICInfo;
		std::vector<TablePlayer> WinPlayer;

		
		for (size_t i = 0; i < PLAYER_NUM; ++i)
		{
			if (i != m_nBankerPos)
			{
				uint32 playerScore = 0;

				int curScore = 0;
				uint8 result = sRuleMgr.Compare(bankerCards, PlayerPos[i].cards); //比较庄家闲家牌型大小
				//Log.Debug("PGChannelInterface::InitGameOverState", "庄家与闲家%d比牌结果：%d ", i, result);
				if (result == en_PGCompareResult_Less) // 庄家输
				{									   //检测杠数
					BarType firresult = sRuleMgr.CheckBarType(PlayerPos[i].cards.firtype, PlayerPos[i].cards.firpoint);
					BarType secresult = sRuleMgr.CheckBarType(PlayerPos[i].cards.sectype, PlayerPos[i].cards.secpoint);
					BarType bartype = sRuleMgr.CompareBarType(firresult, secresult); //最终可取积分杠数
					if (bartype == en_BarType_Head)
					{
						bankerLossScore += EveryScore(PlayerPos[i].mapNumScore, 1);
						playerScore = EveryScore(PlayerPos[i].mapNumScore, 1);
						Log.Debug("PGChannelInterface::CalcScoreResult", "1道杠：闲家座位号:%d 当前积分：%d  ", i, PlayerPos[i].curScore);
					}
					else if (bartype == en_BarType_Second)
					{
						bankerLossScore += EveryScore(PlayerPos[i].mapNumScore, 2);
						playerScore = EveryScore(PlayerPos[i].mapNumScore, 2);
						Log.Debug("PGChannelInterface::CalcScoreResult", "2道杠：闲家座位号:%d 当前积分：%d  ", i, PlayerPos[i].curScore);
					}
					else
					{
						bankerLossScore += EveryScore(PlayerPos[i].mapNumScore, 3);
						playerScore = EveryScore(PlayerPos[i].mapNumScore, 3);
						Log.Debug("PGChannelInterface::CalcScoreResult", "3道杠：闲家座位号:%d 当前积分：%d  ", i, PlayerPos[i].curScore);
					}
					//闲家输赢信息统计
					curScore = playerScore;
					PlayerPos[i].curScore +=playerScore;
					PlayerPos[i].isWin = en_PGCompareResult_Greater;
					PlayerPos[i].win_count += 1;
					
				}

				else if (result == en_PGCompareResult_Greater)
				{

					BarType firresult = sRuleMgr.CheckBarType(bankerCards.firtype, bankerCards.firpoint);
					BarType secresult = sRuleMgr.CheckBarType(bankerCards.sectype, bankerCards.secpoint);
					BarType bartype = sRuleMgr.CompareBarType(firresult, secresult);
					if (bartype == en_BarType_Head)
					{
						bankerWinScore += EveryScore(PlayerPos[i].mapNumScore, 1);
						playerScore = EveryScore(PlayerPos[i].mapNumScore, 1);
						Log.Debug("PGChannelInterface::CalcScoreResult", "1道杠：闲家座位号:%d 当前积分：%d  ", i, PlayerPos[i].curScore);
					}
					else if (bartype == en_BarType_Second)
					{
						bankerWinScore += EveryScore(PlayerPos[i].mapNumScore, 2);
						playerScore = EveryScore(PlayerPos[i].mapNumScore, 2);
						Log.Debug("PGChannelInterface::CalcScoreResult", "2道杠：闲家座位号:%d 当前积分：%d  ", i, PlayerPos[i].curScore);
					}
					else
					{
						bankerWinScore += EveryScore(PlayerPos[i].mapNumScore, 3);
						playerScore = EveryScore(PlayerPos[i].mapNumScore, 3);
						Log.Debug("PGChannelInterface::CalcScoreResult", "3道杠：闲家座位号:%d 当前积分：%d  ", i, PlayerPos[i].curScore);
					}

					++winCount;

					//闲家输赢信息统计
					curScore = -playerScore;
					PlayerPos[i].curScore -= playerScore;
					PlayerPos[i].isWin = en_PGCompareResult_Less;
					PlayerPos[i].lose_count += 1; //玩家输次数
				
				}
				else
					PlayerPos[i].isWin = en_PGCompareResult_Draw;

				//	闲家每轮输赢情况
				PlayerPos[i].roundWins = curScore;
				Log.Debug("PGChannelInterface::CalcScoreResult", "name[%s],pos[%d], curScore:%d  roundWins:%d",
						  GetPlayerName(PlayerPos[i]), PlayerPos[i].pos, PlayerPos[i].curScore, PlayerPos[i].roundWins);
				WinPlayer.push_back(PlayerPos[i]);
				// 添加进发出的牌列表
				m_lstOutCards.push_back(PlayerPos[i]);
				Log.Debug("PGChannelInterface::InitGameOverState", "闲家座位号 :%d 牌值：%d,%d,%d,%d", i, PlayerPos[i].cards.vecCards[0], PlayerPos[i].cards.vecCards[1],
							PlayerPos[i].cards.vecCards[2], PlayerPos[i].cards.vecCards[3]);
			}
		}

		//庄家本轮输赢
		finishWinScore = bankerWinScore - bankerLossScore;
		Log.Debug("PGChannelInterface::CalcScoreResult", " m_BaseScore: %d finishWinScore：%d ", m_BaseScore, finishWinScore);
		if (!m_bGameOver)
		{
			// 庄家的牌
			m_lstOutCards.push_back(PlayerPos[m_nBankerPos]);
		}

		Log.Warning("PGProtocolsManager::CreateBankerLookCardsPacket", "列表大小1：%d", m_lstOutCards.size());
		//庄家输赢类型
		if (winCount == 3)
			m_rType = en_ResultType_FullWin;
		else if (winCount == 0)
			m_rType = en_ResultType_FullFaild;
		else
			m_rType = en_ResultType_Normal;

		// 计算庄家盈利
		if (finishWinScore > 0)
		{
			PlayerPos[m_nBankerPos].roundWins = finishWinScore;
			PlayerPos[m_nBankerPos].isWin = en_PGCompareResult_Greater;
			m_BaseScore += finishWinScore;
			PlayerPos[m_nBankerPos].win_count += 1;
		}
		else
		{
			PlayerPos[m_nBankerPos].isWin = en_PGCompareResult_Less;
			PlayerPos[m_nBankerPos].lose_count += 1;
			if(m_BaseScore + finishWinScore >= 0)
			{
				PlayerPos[m_nBankerPos].roundWins = finishWinScore;
				m_BaseScore += finishWinScore;
			}
			//庄家不够赔
			else
			{
				Log.Debug("PGChannelInterface::CalcScoreResult", "庄家不够赔:  m_BaseScore: %d finishWinScore：%d ", m_BaseScore ,finishWinScore);
				if (WinPlayer.size())
				{
					Log.Debug("PGChannelInterface::CalcScoreResult", "WinPlayer.size[%d]", WinPlayer.size());
					uint8 result = 0;

					if(WinPlayer.size() == 1)
					{//一个赢家
						Analysis(WinPlayer, 4);
					}
					if(WinPlayer.size() == 2)
					{//两个赢家
						result = sRuleMgr.Compare(WinPlayer[0].cards, WinPlayer[1].cards, en_ComOpt_First);
						Log.Debug("PGChannelInterface::CalcScoreResult", "Only two winplayer：name[%s],pos[%d] name[%s],pos[%d]",
								  GetPlayerName(WinPlayer[0]), WinPlayer[0].pos,
								  GetPlayerName(WinPlayer[1]), WinPlayer[1].pos);
						Log.Debug("PGChannelInterface::CalcScoreResult", "First Cardtype is [%d]", result);
						//一组牌相等
						if (result == en_PGCompareResult_Draw)
						{
							result = sRuleMgr.Compare(WinPlayer[0].cards, WinPlayer[1].cards, en_ComOpt_Second);
							Log.Debug("PGChannelInterface::CalcScoreResult", "Second Cardtype is [%d]", result);
							//二组牌也相等
							if (result == en_PGCompareResult_Draw)
							{
								if (WinPlayer[0].pos < WinPlayer[1].pos)
									Analysis( WinPlayer,1);
								else
									Analysis(WinPlayer, 0);
							}
							else if (result == en_PGCompareResult_Greater)
								Analysis(WinPlayer, 1);
							else
								Analysis(WinPlayer, 0);
						}

						else if(result == en_PGCompareResult_Greater)
							Analysis(WinPlayer, 1);
						else
							Analysis(WinPlayer, 0);
					}
					if (WinPlayer.size() == 3)
					{//三个赢家
						Log.Debug("PGChannelInterface::CalcScoreResult", "Have three winplayer：name[%s],pos[%d] name[%s],pos[%d] name[%s],pos[%d]",
								  GetPlayerName(WinPlayer[0]), WinPlayer[0].pos,
								  GetPlayerName(WinPlayer[1]), WinPlayer[1].pos,
								  GetPlayerName(WinPlayer[2]), WinPlayer[2].pos);
						uint32 freescore = 0;
						std::vector<Cards> cardstype;
						std::vector<TablePlayer> Free = WinPlayer;
						uint8 result1 = sRuleMgr.Compare(WinPlayer[0].cards, WinPlayer[1].cards, en_ComOpt_First);
						uint8 result2 = sRuleMgr.Compare(WinPlayer[0].cards, WinPlayer[2].cards, en_ComOpt_First);
						uint8 result3 = sRuleMgr.Compare(WinPlayer[1].cards, WinPlayer[2].cards, en_ComOpt_First);
						Log.Debug("PGChannelInterface::CalcScoreResult", " First CardTpye Com result1[%d] result[%d] result[%d]", result1, result2, result3);
						//比较第一组牌型
						if (SameNum(result1, result2, result3) == 3)
						{
							result1 = sRuleMgr.Compare(WinPlayer[0].cards, WinPlayer[1].cards, en_ComOpt_Second);
							result2 = sRuleMgr.Compare(WinPlayer[0].cards, WinPlayer[2].cards, en_ComOpt_Second);
							result3 = sRuleMgr.Compare(WinPlayer[1].cards, WinPlayer[2].cards, en_ComOpt_Second);
							Log.Debug("PGChannelInterface::CalcScoreResult", " Second CardTpye Com result1[%d] result[%d] result[%d]", result1, result2, result3);
							//比较第二组牌型
							if (SameNum(result1, result2, result3) == 3)
							{//先发牌的先赔付，三个一样
								Analysis(WinPlayer, 2);
							}
							else if (SameNum(result1, result2, result3) == 2)
							{//其中两个一样
								uint8 Se;
								TablePlayer max = WinPlayer[0];
								for (uint8 i = 0; i < WinPlayer.size(); ++i)
								{
									Se = sRuleMgr.Compare(max.cards, WinPlayer[i].cards, en_ComOpt_Second);
									if (Se == en_PGCompareResult_Draw)
									{
										Analysis(max, WinPlayer, i);
									}
									else if (Se == en_PGCompareResult_Less)
										max = WinPlayer[i];
								}

							}
							else
							{//都不一样
                                 Analysis(WinPlayer,3);
                            }
									
																																																																																																												
						}
						else if (SameNum(result1, result2, result3) == 2)
						{

							uint8 Se;
							TablePlayer max = WinPlayer[0];

							for (uint8 i = 0; i < WinPlayer.size(); ++i)
							{
								Se = sRuleMgr.Compare(max.cards, WinPlayer[i].cards, en_ComOpt_First);
								//第一组牌分析
								if (Se == en_PGCompareResult_Draw)
								{
									Se = sRuleMgr.Compare(max.cards, WinPlayer[i].cards, en_ComOpt_Second);
									if (Se == en_PGCompareResult_Draw)
									{	//第二组牌分析
										Analysis(max, WinPlayer, i);
									}
									else if (Se == en_PGCompareResult_Greater)
									{
										Analysis(max, WinPlayer[i], WinPlayer, i);
									}
									else
									{
										Analysis(WinPlayer[i], max, WinPlayer, i);
									}
								}
								else if (Se == en_PGCompareResult_Less)
									max = WinPlayer[i];
							}
						}
						else
						{
                            Analysis(WinPlayer,3);
                        }
						

					}
						
				}
				PlayerPos[m_nBankerPos].roundWins = -m_BaseScore;
				m_BaseScore -= m_BaseScore;
			}
		
		}
		Log.Debug("PGChannelInterface::InitGameOverState", "bankerWinScore:%d bankerLossScore：%d 底分(Basescore)剩余：%d ", bankerWinScore, bankerLossScore, m_BaseScore);
		Log.Debug("PGChannelInterface::InitGameOverState", "m_nBankerPos :%d m_rType：%d roundWins：%d", m_nBankerPos, m_rType, PlayerPos[m_nBankerPos].roundWins);
	}
	const char *PGChannelInterface::GetPlayerName(TablePlayer player)
	{
          CharPtr pChr = sCharMgr.getByHandle((player).player._handle);
          return pChr->getStringField("name").c_str();
    }
	TablePlayer PGChannelInterface::Analysis(TablePlayer max, std::vector<TablePlayer> WinPlayer, const uint8 &i)
	{
			TablePlayer center = WinPlayer[i];
			TablePlayer min;
			int freescore;
			freescore = m_BaseScore - PlayerPos[FindRealPos(max)].roundWins - PlayerPos[FindRealPos(center)].roundWins;
			if (freescore < 0)
			{
				if (max.pos < center.pos)
				{
					(PlayerPos[FindRealPos(center)].curScore += (m_BaseScore - PlayerPos[FindRealPos(max)].roundWins) - PlayerPos[FindRealPos(center)].roundWins);
					PlayerPos[FindRealPos(center)].roundWins = (m_BaseScore - PlayerPos[FindRealPos(max)].roundWins);
				}
				else
				{
					(PlayerPos[FindRealPos(max)].curScore += (m_BaseScore - PlayerPos[FindRealPos(center)].roundWins) - PlayerPos[FindRealPos(max)].roundWins);
					PlayerPos[FindRealPos(max)].roundWins = (m_BaseScore - PlayerPos[FindRealPos(center)].roundWins);
				}
				for (uint8 k = 0; k < WinPlayer.size(); ++k)
				{
					if (WinPlayer[k].pos != max.pos && WinPlayer[k].pos != center.pos)
					{
						(PlayerPos[FindRealPos(WinPlayer[k])].curScore += 0 - PlayerPos[FindRealPos(WinPlayer[k])].roundWins);
						PlayerPos[FindRealPos(WinPlayer[k])].roundWins = 0;
					}
				}
			}

			else
			{
				for (uint8 k = 0; k < WinPlayer.size(); ++k)
				{
					if (WinPlayer[k].pos != max.pos && WinPlayer[k].pos != center.pos)
					{
						(PlayerPos[FindRealPos(WinPlayer[k])].curScore += freescore - PlayerPos[FindRealPos(WinPlayer[k])].roundWins);
						PlayerPos[FindRealPos(WinPlayer[k])].roundWins = freescore;
						min = WinPlayer[k];
					}
				}
			}

			return min;
	}
	void PGChannelInterface::Analysis(TablePlayer max, TablePlayer center, std::vector<TablePlayer> WinPlayer, const uint8 &i)
	{
		TablePlayer min;
		int freescore;
		for (uint8 k = 0; k < WinPlayer.size(); ++k)
		{
			if (WinPlayer[k].pos != max.pos && WinPlayer[k].pos != center.pos)
			{
				min = WinPlayer[k];
			}
		}

		freescore = m_BaseScore - PlayerPos[FindRealPos(max)].roundWins - PlayerPos[FindRealPos(center)].roundWins;
		if (freescore < 0)
		{
			(PlayerPos[FindRealPos(center)].curScore+= (m_BaseScore - PlayerPos[FindRealPos(max)].roundWins) - PlayerPos[FindRealPos(center)].roundWins) ;
			PlayerPos[FindRealPos(center)].roundWins = (m_BaseScore - PlayerPos[FindRealPos(max)].roundWins);

			(PlayerPos[FindRealPos(min)].curScore += 0 - PlayerPos[FindRealPos(min)].roundWins);
			PlayerPos[FindRealPos(min)].roundWins = 0;
		}
		else
		{
			(PlayerPos[FindRealPos(min)].curScore += freescore - PlayerPos[FindRealPos(min)].roundWins);
			PlayerPos[FindRealPos(min)].roundWins = freescore;
		}
	}
	void PGChannelInterface::Analysis(std::vector<TablePlayer> WinPlayer, const uint8 &num)
	{
		int freescore;
		if(num == 0)
		{
			(PlayerPos[FindRealPos(WinPlayer[0])].curScore += (m_BaseScore - PlayerPos[FindRealPos(WinPlayer[1])].roundWins) - PlayerPos[FindRealPos(WinPlayer[0])].roundWins);
			PlayerPos[FindRealPos(WinPlayer[0])].roundWins = (m_BaseScore - PlayerPos[FindRealPos(WinPlayer[1])].roundWins);
		}
		if(num == 1)
		{
			(PlayerPos[FindRealPos(WinPlayer[1])].curScore += (m_BaseScore - PlayerPos[FindRealPos(WinPlayer[0])].roundWins) - PlayerPos[FindRealPos(WinPlayer[1])].roundWins);
			PlayerPos[FindRealPos(WinPlayer[1])].roundWins = (m_BaseScore - PlayerPos[FindRealPos(WinPlayer[0])].roundWins);
		}
		if(num == 2)
		{
			freescore = m_BaseScore - PlayerPos[FindRealPos(FindBefore(WinPlayer, 1))].roundWins - PlayerPos[FindRealPos(FindBefore(WinPlayer, 2))].roundWins;
			if(freescore < 0)
			{
				(PlayerPos[FindRealPos(FindBefore(WinPlayer, 2))].curScore += (m_BaseScore - PlayerPos[FindRealPos(FindBefore(WinPlayer, 1))].roundWins) - PlayerPos[FindRealPos(FindBefore(WinPlayer, 2))].roundWins);
				PlayerPos[FindRealPos(FindBefore(WinPlayer, 2))].roundWins = (m_BaseScore - PlayerPos[FindRealPos(FindBefore(WinPlayer, 1))].roundWins);

				(PlayerPos[FindRealPos(FindBefore(WinPlayer, 3))].curScore += 0 - PlayerPos[FindRealPos(FindBefore(WinPlayer, 3))].roundWins);
				PlayerPos[FindRealPos(FindBefore(WinPlayer, 3))].roundWins = 0;
			}
			else
			{
				(PlayerPos[FindRealPos(FindBefore(WinPlayer, 3))].curScore += freescore - PlayerPos[FindRealPos(FindBefore(WinPlayer, 3))].roundWins);
				PlayerPos[FindRealPos(FindBefore(WinPlayer, 3))].roundWins = freescore;
			}
		}
		if(num == 3)
		{
			Log.Debug("PGChannelInterface::Analysis", "name[%s],pos[%d],roundwins[%d] name[%s],pos[%d],roundwins[%d] name[%s],pos[%d],roundwins[%d]",
					  GetPlayerName(FindMax(WinPlayer, 1, 1)), FindMax(WinPlayer, 1, 1).pos,PlayerPos[FindRealPos(FindMax(WinPlayer, 1, 1))].roundWins,
					  GetPlayerName(FindMax(WinPlayer, 2, 1)), FindMax(WinPlayer, 2, 1).pos,PlayerPos[FindRealPos(FindMax(WinPlayer, 2, 1))].roundWins,
					  GetPlayerName(FindMax(WinPlayer, 3, 1)), FindMax(WinPlayer, 3, 1).pos,PlayerPos[FindRealPos(FindMax(WinPlayer, 3, 1))].roundWins);

			freescore = m_BaseScore - PlayerPos[FindRealPos(FindMax(WinPlayer, 1, 1))].roundWins - PlayerPos[FindRealPos(FindMax(WinPlayer, 2, 1))].roundWins;
			Log.Debug("PGChannelInterface::Analysis", "baseScore [%d] freescore [%d]", m_BaseScore, freescore);
			Log.Debug("PGChannelInterface::Analysis", "name[%s],pos[%d] name[%s],pos[%d] name[%s],pos[%d]",
					  GetPlayerName(FindMax(WinPlayer, 1, 1)), FindMax(WinPlayer, 1, 1).pos,
					  GetPlayerName(FindMax(WinPlayer, 2, 1)), FindMax(WinPlayer, 2, 1).pos,
					  GetPlayerName(FindMax(WinPlayer, 3, 1)), FindMax(WinPlayer, 3, 1).pos);
			if (freescore < 0)
			{
				(PlayerPos[FindRealPos(FindMax(WinPlayer, 2, 1))].curScore += (m_BaseScore - PlayerPos[FindRealPos(FindMax(WinPlayer, 1, 1))].roundWins) - PlayerPos[FindRealPos(FindMax(WinPlayer, 2, 1))].roundWins);
				PlayerPos[FindRealPos(FindMax(WinPlayer, 2, 1))].roundWins = (m_BaseScore - PlayerPos[FindRealPos(FindMax(WinPlayer, 1, 1))].roundWins);

				(PlayerPos[FindRealPos(FindMax(WinPlayer, 3, 1))].curScore += 0 - PlayerPos[FindRealPos(FindMax(WinPlayer, 3, 1))].roundWins);
				PlayerPos[FindRealPos(FindMax(WinPlayer, 3, 1))].roundWins = 0;
				Log.Debug("PGChannelInterface::Analysis", "name[%s],pos[%d] name[%s],pos[%d] name[%s],pos[%d]",
						  GetPlayerName(FindMax(WinPlayer, 1, 1)), FindMax(WinPlayer, 1, 1).pos,
						  GetPlayerName(FindMax(WinPlayer, 2, 1)), FindMax(WinPlayer, 2, 1).pos,
						  GetPlayerName(FindMax(WinPlayer, 3, 1)), FindMax(WinPlayer, 3, 1).pos); 
			}
			else
			{
				(PlayerPos[FindRealPos(FindMax(WinPlayer, 3, 1))].curScore += freescore - PlayerPos[FindRealPos(FindMax(WinPlayer, 3, 1))].roundWins);
				PlayerPos[FindRealPos(FindMax(WinPlayer, 3, 1))].roundWins = freescore;
			}
			Log.Debug("PGChannelInterface::Analysis", "name[%s],pos[%d],roundwins[%d] name[%s],pos[%d],roundwins[%d] name[%s],pos[%d],roundwins[%d]",
					  GetPlayerName(FindMax(WinPlayer, 1, 1)), FindMax(WinPlayer, 1, 1).pos, PlayerPos[FindRealPos(FindMax(WinPlayer, 1, 1))].roundWins,
					  GetPlayerName(FindMax(WinPlayer, 2, 1)), FindMax(WinPlayer, 2, 1).pos, PlayerPos[FindRealPos(FindMax(WinPlayer, 2, 1))].roundWins,
					  GetPlayerName(FindMax(WinPlayer, 3, 1)), FindMax(WinPlayer, 3, 1).pos, PlayerPos[FindRealPos(FindMax(WinPlayer, 3, 1))].roundWins);
		}
		if (num == 4)
		{
			PlayerPos[FindRealPos(WinPlayer[0])].curScore += m_BaseScore - PlayerPos[FindRealPos(WinPlayer[0])].roundWins;
			PlayerPos[FindRealPos(WinPlayer[0])].roundWins = m_BaseScore;
		}
	}

	TablePlayer PGChannelInterface::FindBefore(std::vector<TablePlayer> Free ,const uint8 &num)
	{
		std::vector<TablePlayer> nFree = Free;
		TablePlayer nbefore;

		for (uint8 k = 1; k <= num; ++k)
		{
			TablePlayer before = nFree[0];
			uint8 b = 0;

			for (uint8 i = 0; i < nFree.size(); ++i)
			{
				if(nFree.size() == 1)
					return nFree[0];
				if (before.pos > nFree[i].pos)
				{
					before = nFree[i];
					b = i;
				}
			}
			nbefore = before;
			nFree.erase(nFree.begin() + b);
		}
		return nbefore;
	}
	TablePlayer PGChannelInterface::FindMax(std::vector<TablePlayer> CardsType, const uint8 &num, const uint8 opt)
	{

		std::vector<TablePlayer> cardstype = CardsType;
		TablePlayer nmax;
		for (uint8 k = 1; k <= num; ++k)
		{
			TablePlayer max = cardstype[0];
			uint8 b = 0;
			uint8 result;

			for (uint8 i = 0; i < cardstype.size(); ++i)
			{
				result = sRuleMgr.Compare(max.cards, cardstype[i].cards, opt);
				if (result == en_PGCompareResult_Less)
				{
					max = cardstype[i];
					b = i;
				}
			}
			nmax = max;
			cardstype.erase(cardstype.begin() + b);
		}
		
		return nmax;
	}
	uint8 PGChannelInterface::FindRealPos(TablePlayer Ps)
	{
		for(uint8 i = 0; i < PlayerPos.size(); ++i)
			if(Ps.pos == PlayerPos[i].pos)
				return i;
	}
	uint8 PGChannelInterface::SameNum(const uint8 & res1, const uint8 & res2,const uint8 & res3)
	{
		if ((res1 == res2) && (res1 == en_PGCompareResult_Draw) ||
			(res1 == res3) && (res3 == en_PGCompareResult_Draw) ||
			(res2 == res3) && (res2 == en_PGCompareResult_Draw))
			return 3;
		else if (res1 == en_PGCompareResult_Draw ||
				 res2 == en_PGCompareResult_Draw ||
				  res3 == en_PGCompareResult_Draw)
			return 2;
		else
			return 1;
		}
	//游戏结算记录
	void PGChannelInterface::CalcGameResultLog()
	{
		//uint32 banker_pid = 0;
		//uint32 win_pid = 0;
		std::vector<TablePlayer>::iterator itSeat, eiSeat = PlayerPos.end();
		for (itSeat = PlayerPos.begin(); itSeat != eiSeat; ++itSeat)
		{
			if ((*itSeat).player.isNull())
				continue;

			CharPtr pChr = sCharMgr.load((*itSeat).player._handle);
			if (pChr.isNull())
				continue;

			uint32 pid = 0;
			UserPtr pUser = sUserMgr.load(pChr->getUInt32Field("userid"));
			if (!pUser.isNull())
				pid = pUser->getUInt32Field("platform_id");
			else // 机器人直接等于他的角色ID就行了
				pid = pChr->getHandle();

			CenterBattlePlayerWinLose cbpw;
			cbpw.platform_id = pid;
			cbpw.char_id = pChr->getHandle();
			cbpw.vip_icon = sVipCardMgr.GetUsedVipId(pChr);
			cbpw.winLoseScore = (*itSeat).roundWins;
			cbpw.player_nick = pChr->getStringField("name");
			cbpw.player_desc = pChr->getStringField("desc");

			Json::Value val, val1, val2, val3, val4 ,val5;
			Json::FastWriter w;
			val1["赢次数"] = (*itSeat).win_count;		// 赢次数
			val2["输次数"] = (*itSeat).lose_count;		// 输次数
			val3["当庄次数"] = (*itSeat).banker_count;  // 当庄次数
			//val4[""] = (*itSeat).noniu_count;   // 
			//val5[""] = (*itSeat).lianZhuang;	// 

			// 保证节点里面的顺序
			val["tongji"].append(val1);
			val["tongji"].append(val2);
			val["tongji"].append(val3);
			//val["tongji"].append(val6);
			//val["tongji"].append(val7);

			val["isBanker"] = (*itSeat).pos == m_nBankerPos; // 是否庄家

			cbpw.json_data = w.write(val);
			m_btLog.player_winLose.push_back(cbpw);
		}

		if (m_bGameOver)
		{
			m_btLog.bFinal = true;
		}

		m_btLog.bHaveVedio = false;
		m_btLog.loop_id = m_nLoopId;
		if (m_bAddCenterBattleLog)
			sCenterBattleLogMgr.AddCenterBattleRecordLog(m_btLog);
	}
	//广播下注积分
	// void PGChannelInterface::BroadcastSeatChip(CharPtr &pChr, const uint32 &num, const uint32 &score, bool bLock)
	// {
	// 	if (pChr.isNull())
	// 		return;
	// 	if(bLock)
	// 	{
	// 		uint32 score;
	// 		std::map<uint32, uint32>::iterator mapiter = mapNumScore.begin();
	// 		std::vector<TablePlayer>::iterator iter, ei = PlayerPos.end();
	// 		for (iter = PlayerPos.begin(); iter != ei; ++iter)
	// 		{
	// 			if ((*iter).player._handle == pChr->getHandle())
	// 			{
	// 				for (; mapiter != mapNumScore.end(); ++mapiter)
	// 				{
	// 					(*iter).AddSeatChip(mapiter->first, mapiter->second);
	// 					score += mapiter->second;
	// 				}
	// 				(*iter).isChin = true;
	// 				break;
	// 			}
	// 		}
	// 	}

	// }

			//小结算确认
	void PGChannelInterface::AskIsRoundPGCalc(CharPtr &pChr, const uint8 &ask)
	{
		if (pChr.isNull())
			return;
		WorldPacket packet;
		WSSocketPtr socket = pChr->getSocket();
		// 通过角色数据获取玩家的牌桌数据
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		if (!pTp)
			return;

		uint8 calcNum = 0;
		if(ask)
			pTp->IsCalC = true;

		std::vector<TablePlayer>::iterator iter = PlayerPos.begin();
		for (; iter != PlayerPos.end(); ++iter)
		{
			if ((*iter).IsCalC)
				++calcNum;
		}
		if(calcNum == 4)
			m_bIsAllCalc = true;

		if (sProtocolsMgr.CreateAskIsRoundPGCalcPacket(&packet,ask))
			socket->SendPacket(&packet);
	}
	TablePlayer *PGChannelInterface::GetTablePlayer(const uint32 chrId)
	{
		TablePlayer *pTp = NULL;
		std::vector<TablePlayer>::iterator iter = PlayerPos.begin();
		for (; iter != PlayerPos.end(); ++iter)
		{
			if (!(*iter).player.isNull() && (*iter).player._handle == chrId)
			{
				pTp = &(*iter);
				break;
			}
		}

		return pTp;
	}
	//添加下注积分信息
	uint32 PGChannelInterface::AddChips(CharPtr &pChr, const uint32 & num, const uint32 & score,bool bLock)
	{
		if(pChr.isNull())
			return en_ChipsInResult_Faild;
		if (m_curState != en_ChannelState_ChipIn)
			return en_ChipsInResult_NotChipTime;
		uint32 cursore;
		if (bLock)
		{ 
			std::vector<TablePlayer>::iterator iter, ei = PlayerPos.end();
			for (iter = PlayerPos.begin(); iter != ei; ++iter)
			{
				if ((*iter).player._handle == pChr->getHandle())
				{
					(*iter).surplusScore -=score;
					cursore = (*iter).surplusScore;
					Log.Debug("PGChannelInterface::AddChips", "num:%d Score:%d sursore:%d ", num, score, cursore);
					(*iter).AddSeatChip(num, score);
					(*iter).isOnceChin = true;
					if (num == m_nNumBar)
						(*iter).isChin = true;
					break;
				}
			}
		}
		return cursore;
	}
	std::map<uint32, uint32> PGChannelInterface::GetNumChips(CharPtr &pChr)
	{
		WSSocketPtr socket = pChr->getSocket();
		// 通过角色数据获取玩家的牌桌数据
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		std::map<uint32, uint32> numchips = pTp->mapNumScore;

		return numchips;
	}
	uint8 PGChannelInterface::PlayerSeatNumber(CharPtr &pChr)
	{
		if (pChr.isNull())
			return 5;
		WorldPacket packet;
		uint8 playerpos;
		WSSocketPtr socket = pChr->getSocket();
		// 通过角色数据获取玩家的牌桌数据
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		if (!pTp)
			return 5;
		playerpos = pTp->pos;
		return playerpos;
	}
	//玩家看牌
	void PGChannelInterface::PlayerLookCard(CharPtr &pChr)
	{
		if (pChr.isNull())
			return;
		WorldPacket packet;
		WSSocketPtr socket = pChr->getSocket();
		// 通过角色数据获取玩家的牌桌数据
		TablePlayer * pTp = GetTablePlayer(pChr->getHandle());
		if(!pTp)
			return;
		
		// 做一系列基础判断
		// 游戏状态是否正确
		if (m_curState == en_ChannelState_Move)
		{
			CompareResult result = en_PGCompareResult_None;
			if (sProtocolsMgr.CreatePlayerLookCardTypePacket(&packet, result, *pTp))
				socket->SendPacket(&packet);
		}
			return;
	}
	//玩家摆牌
	void PGChannelInterface::PlayermoveCard(CharPtr &pChr, const uint8 index1, const uint8 index2)
	{
		if (pChr.isNull())
			return;
		WorldPacket packet;
		WSSocketPtr socket = pChr->getSocket();
		// 通过角色数据获取玩家的牌桌数据
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		if (!pTp)
			return;
		if(index1>4||index2>4)
		return;
		Cards card1;
		uint8 result;
		//新摆牌方式
		card1 = (*pTp).Originalcards;
		//是否已经获取提示牌型
		if ((*pTp).IsPrompt)
		{
			card1 = (*pTp).cards;
			(*pTp).Originalcards =  (*pTp).cards;
			(*pTp).IsPrompt = false;
		}
	

		(*pTp).cards = SelfCardsTypeCheck(card1, index1, index2, result);
		Log.Debug("PGChannelInterface::PlayermoveCard", "一二组牌大小结果：%d", result);
		(*pTp).movecardresult = result;
		(*pTp).IsMovecard =true;
		if (m_curState == en_ChannelState_Move)
			if (sProtocolsMgr.CreatePlayerMoveCardPacket(&packet, *pTp))
				socket->SendPacket(&packet);
	}
	//玩家摆牌操作最终结果
	void PGChannelInterface::PlayerMoveCardFinish(CharPtr &pChr)
	{

		if (pChr.isNull()) 
			return;
		WorldPacket packet;
		WSSocketPtr socket = pChr->getSocket();
		uint8 result;
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		if (!pTp)
			return;
		(*pTp).IsMovefinish = true;	
		if((*pTp).IsMovecard)
			result = pTp->movecardresult;
		else
		{
			(*pTp).cards = SelfCardsTypeCheck((*pTp).cards, 0, 0, result);
			(*pTp).movecardresult = result;
			Log.Debug("PGChannelInterface::PlayerMoveCardFinish", "直接开牌：%d", result);
		}
		//若不符合出牌规则，交换一二组牌
		if(result == en_PGCompareResult_Less)
		{
			// swap((*pTp).cards.vecCards[0], (*pTp).cards.vecCards[2]); //交换牌的位置
			// swap((*pTp).cards.vecCards[1], (*pTp).cards.vecCards[3]); //交换牌的位置

			PaiGowType vecCards1 = (*pTp).cards.vecCards[0];
			PaiGowType vecCards2 = (*pTp).cards.vecCards[1];
			(*pTp).cards.vecCards[0] = (*pTp).cards.vecCards[2];
			(*pTp).cards.vecCards[1] = (*pTp).cards.vecCards[3];
			(*pTp).cards.vecCards[2] = vecCards1;
			(*pTp).cards.vecCards[3] = vecCards2;

			uint8 firtype = (*pTp).cards.firtype;
			uint8 firpoint = (*pTp).cards.firpoint;
			(*pTp).cards.firtype = (*pTp).cards.sectype;
			(*pTp).cards.firpoint = (*pTp).cards.secpoint;
			(*pTp).cards.sectype = firtype;
			(*pTp).cards.secpoint = firpoint;
			(*pTp).movecardresult = en_PGCompareResult_Greater;
			Log.Debug(
				"PGChannelInterface::PlayerMoveCardFinish",
				"玩家昵称:%s pos:%d  %d-%d(%d %d)  %d-%d result：%d",
				GetPlayerName((*pTp)), (*pTp).pos,
				(*pTp).cards.firtype, (*pTp).cards.firpoint,
				(*pTp).cards.vecCards[0].point, (*pTp).cards.vecCards[1].point,
				(*pTp).cards.sectype, (*pTp).cards.secpoint,
				(*pTp).movecardresult);
			//result = en_PGCompareResult_Greater;

		}

		Log.Debug("PGChannelInterface::PlayerMoveCardFinish", "一二组牌大小结果：%d", result);
		//换牌后第一组牌结果如果大于第二组则换牌失败，系统自动换牌到达条件
		// if (result == en_PGCompareResult_Greater)
		// {
		// 	//
		// 	(*pTp).cards = SystemProcessCardsType(*pTp);
		// }
		if(sProtocolsMgr.CreatePlayerMoveCardPacket(&packet, *pTp))
			socket->SendPacket(&packet);
		if (m_curState == en_ChannelState_Move)
			if (sProtocolsMgr.CreatePlayerMoveCardResultPacket(&packet, result))
				socket->SendPacket(&packet);
	}
	//玩家获取提示牌型
	void PGChannelInterface::PlayerPromptCardsType(CharPtr &pChr)
	{
		if (pChr.isNull())
			return;
		WorldPacket packet;
		WSSocketPtr socket = pChr->getSocket();
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		if (!pTp)
			return;
		//最优算法
		(*pTp).cards = SystemProcessCardsType(*pTp);
		//已经提示
		(*pTp).IsPrompt = true;
		if (m_curState == en_ChannelState_Move)
			if (sProtocolsMgr.CreatePlayerLookCardTypePacket(&packet, 2, *pTp))
				socket->SendPacket(&packet);
	}
	//检测自己两两组合牌型
	Cards PGChannelInterface::SelfCardsTypeCheck(Cards card1,const uint8 index1, const uint8 index2,uint8 & result,bool Isnew)
	{
		Cards card2;

		if(index1 != index2 && Isnew)
		{//适用手动摆牌
			swap(card1.vecCards[index1], card1.vecCards[0]); //交换牌的位置
			swap(card1.vecCards[index2], card1.vecCards[1]); //交换牌的位置
		}
		if(!Isnew)
		{//适用自动检测
			swap(card1.vecCards[index1], card1.vecCards[index2]); //交换牌的位置
		}
		
		for (uint32 i = 0; i < card1.vecCards.size(); ++i)
		{
			card2.InsertCard(card1.vecCards[i], m_specialtype); //重新计算牌型及点数
		//	Log.Debug("PGChannelInterface::SelfCardsTypeCheck", "交换之后的牌序 %d  %d", i, card2.vecCards[i]);
		}
		//将一二组牌分别由原来的两张扩充为四张以满足比牌要求
		Cards temp1, temp2;
		//模拟为第一组牌
		temp1.vecCards.push_back(card2.vecCards[0]);
		temp1.vecCards.push_back(card2.vecCards[1]);
		temp1.firtype = card2.firtype;
		temp1.firpoint = card2.firpoint;
		//模拟为第二组牌
		temp1.vecCards.push_back(card2.vecCards[0]);
		temp1.vecCards.push_back(card2.vecCards[1]);
		temp1.sectype = card2.firtype;
		temp1.secpoint = card2.firpoint;

		temp2.vecCards.push_back(card2.vecCards[2]);
		temp2.vecCards.push_back(card2.vecCards[3]);
		temp2.firtype = card2.sectype;
		temp2.firpoint = card2.secpoint;
		temp2.vecCards.push_back(card2.vecCards[2]);
		temp2.vecCards.push_back(card2.vecCards[3]);
		temp2.sectype = card2.sectype;
		temp2.secpoint = card2.secpoint;

		result = sRuleMgr.Compare(temp1, temp2); //第一组牌与第二组牌比较大小，用于摆牌

		return card2;
	}
	//系统处理满足条件的牌型组合
	Cards PGChannelInterface::SystemProcessCardsType(TablePlayer tp)
	{
		uint8 result;
		 Cards card;
		//普通
		for(uint8 i =0;i < 2;++i)
			for (uint8 j = 2; j < 4; ++j)
			{
					card = SelfCardsTypeCheck(tp.Originalcards, i, j, result,false);
					if (result > en_PGCompareResult_Greater)
					{
						tp.CorrectCardsType.push_back(card);
						//Log.Debug("PGChannelInterface::SystemProcessCardsType", "符合条件结果：%d", result);
					}
			}
		//原始牌型
		Cards card1 = SelfCardsTypeCheck(tp.Originalcards, 0, 0, result,false);
		if (result > en_PGCompareResult_Greater)
		{
			tp.CorrectCardsType.push_back(card1);
			//Log.Debug("PGChannelInterface::SystemProcessCardsType", "符合条件结果：%d", result);
		}
		//一二组交换
		Cards card2 = tp.Originalcards;
		swap(card2.vecCards[0], card2.vecCards[2]);
		Cards card3 = SelfCardsTypeCheck(card2, 1, 3, result,false);
		if (result > en_PGCompareResult_Greater)
		{
			tp.CorrectCardsType.push_back(card3);
			//Log.Debug("PGChannelInterface::SystemProcessCardsType", "符合条件结果：%d", result);
		}

		Log.Debug("PGChannelInterface::SystemProcessCardsType", "满足条件的个数:%d", tp.CorrectCardsType.size());
		Cards maxType;
		//随机选择符合牌型
		/* uint32 pos = RandomUInt(tp.CorrectCardsType.size()-1);
		 std::vector<Cards>::iterator iter = tp.CorrectCardsType.begin() + pos;
		 maxType = (*iter);*/
		//选择符合条件的最大牌型
		maxType = MaximumCardTypeCombination(tp.CorrectCardsType);

		return maxType;
	}
	//返回符合条件的最大牌型组合
	Cards PGChannelInterface::MaximumCardTypeCombination(std::vector<Cards> CardsType, const uint8 &opt)
	{

		uint8 result;
		Cards max = CardsType[0];
		for (uint8 i = 1; i < CardsType.size(); ++i)
		{
			result = sRuleMgr.Compare(max, CardsType[i], opt);
			if (result >= en_PGCompareResult_Less)
			{
				max = CardsType[i];
			}
		}
		Log.Debug("PGChannelInterface::MaximumCardTypeCombination", "最大牌型组合:(%d %d %d %d)   opt[%d]", max.firtype,max.firpoint,max.sectype,max.secpoint,opt);
		return max;
	} 
	//下一玩家切牌信息
	void PGChannelInterface::PlayerCutCards(CharPtr &pChr, const uint8 result)
	{
		if (pChr.isNull())
			return;

		WorldPacket packet;
		WSSocketPtr socket = pChr->getSocket();

		// 通过角色数据获取玩家的牌桌数据
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		if (!pTp)
			return;
		(*pTp).cutresult = result;
		if(result == en_CutCards_No)
		{
			m_lastSaveTime = now();
			pTp->cutcardflag = true;
			++m_cutplayer;

			if (m_cutplayer >= PLAYER_NUM)
			{ // 所有玩家都已经操作
				m_curState = en_ChannelState_ChipIn;
			}
			else
			{ // 改变下一个要切牌的座位，通知所有玩家
				m_nSpeakPos = (m_nSpeakPos + 1) % PLAYER_NUM;
				// 发包
				if (sProtocolsMgr.CreateBroadCutResultPacket(&packet, PlayerPos[m_nSpeakPos], 
				m_nSpeakPos, m_cutplayer, sXmlDataMgr.GetConfXMLValue("CUTCARDSTIME"), false))
					BroadcastPacketBC(&packet);
			}
		}
		
	}
	//当前玩家切牌位置索引
	void PGChannelInterface::PlayerCutCardsPos(CharPtr &pChr, const uint32 cutcardpos)
	{
		if (pChr.isNull())
			return;

		WorldPacket packet;
		WSSocketPtr socket = pChr->getSocket();

		// 通过角色数据获取玩家的牌桌数据
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		if (!pTp)
			return;
		//Log.Debug("PGChannelInterface::PlayerCutCardsPos", "切牌选择结果：%d",(*pTp).cutresult);
		if ((*pTp).cutresult== en_CutCards_Yes)
		{
			//将所切的牌放在最后
			uint32 cutpos = RandomUInt(m_vecCurCards.size()-1);
			PaiGowType CutCardPos = m_vecCurCards.at(cutpos); /*当传回索引cutpos所指的数据，如果cutpos越界，抛出out_of_range*/
			m_vecCurCards.erase(m_vecCurCards.begin() + cutpos);
			m_vecCurCards.push_back(CutCardPos);

			//广播玩家当前切牌操作
			if (sProtocolsMgr.CreateBroadCutCardsPosPacket(&packet, (*pTp).pos, cutcardpos))
				BroadcastPacketBC(&packet);
		}
	}
	//完成切牌选项
	void PGChannelInterface::PlayerCutCardsFinsh(CharPtr &pChr)
	{
		if (pChr.isNull())
			return;

		WorldPacket packet;
		WSSocketPtr socket = pChr->getSocket();

		// 通过角色数据获取玩家的牌桌数据
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		if (!pTp)
			return;
			(*pTp).cutcardfinsh = true;
	}
	// 产生庄家位置
	void PGChannelInterface::SetBankerPos() 
	{
		//庄家锁
		WGS_BANKER_INNER_LOCK

		WorldPacket packet;
		if (m_nLoopBankerMode == en_GameMode_Orderbanker)
		{ // 轮庄模式
			if (m_nLoopId > 1)
			{ // 轮庄模式轮庄逻辑
				//Log.Warning("PGChannelInterface::SetBankerPos", "当前底分：%d  比值:%d 封顶倍数:%d", m_BaseScore, m_BaseScore / m_nBasePoint, m_nTopTimes);
				if (m_BaseScore <= 0 || (m_BaseScore / m_nBasePoint) >= m_nTopTimes) //输完底分或到达切锅倍数
				{
					Log.Warning("PGChannelInterface::SetBankerPos", "到达封顶倍数 ");
					PlayerPos[m_nBankerPos].curScore+=m_BaseScore;
					for (uint8 i = 0; i < PlayerPos.size(); ++i)
					{
						TablePlayer tp = PlayerPos[(m_nBankerPos + i + 1) % PlayerPos.size()];
						if (tp.status == en_PlayStatus_Ready)
						{ // 当前庄家的下一个玩家当庄
							m_nBankerPos = tp.pos;
							Log.Warning("PGChannelInterface::SetBankerPos", "轮庄模式：下一庄家座位号%d ", m_nBankerPos);
							break;
						}
					}
					if(m_BaseScore>0)
					{
						if (sProtocolsMgr.CreateAbandonBankerPacket(&packet, en_AbandonStatus_Multiple)) //到达封顶倍数
						{
							//Log.Warning("PGChannelInterface::SetBankerPos", "到达封顶倍数1 ");
							BroadcastPacketBC(&packet);
						}
					}
					else
					{
						if (sProtocolsMgr.CreateAbandonBankerPacket(&packet, en_AbandonStatus_NoMoney)) //底分输完
							BroadcastPacketBC(&packet);
					}
					m_BaseScore = m_nBasePoint;//下一玩家坐庄，底分设置为默认底分
					//新庄家扣取底分对应的积分
					if (sProtocolsMgr.CreateSetBankerDelScorePacket(&packet, m_nBankerPos, m_BaseScore))
					{
						BroadcastPacketBC(&packet);
						Log.Warning("PGChannelInterface::SetBankerPos", "轮庄模式1：新庄家座位号%d 锅底：%d", m_nBankerPos, m_BaseScore);
					}

					SendCenterBattleInfo(m_nBasePoint);
			
				}
				else
				{	
					if (m_bankerAnswer == en_AnswerType_Yes) //轮庄下切锅
					{
						PlayerPos[m_nBankerPos].curScore += m_BaseScore;
						for (uint8 i = 0; i < PlayerPos.size(); ++i)
						{
							TablePlayer tp = PlayerPos[(m_nBankerPos + i + 1) % PlayerPos.size()];
							if (tp.status == en_PlayStatus_Ready)
							{ // 当前庄家的下一个玩家当庄
								m_nBankerPos = tp.pos;
								Log.Warning("PGChannelInterface::SetBankerPos", "轮庄模式下切锅下一玩家座位：%d ", tp.pos);
								break;
							}
						}

						if (sProtocolsMgr.CreateAbandonBankerPacket(&packet, en_AbandonStatus_Active)) //主动让庄
							BroadcastPacketBC(&packet);
						m_BaseScore = m_nBasePoint;
						//新庄家扣取底分对应的积分
						if (sProtocolsMgr.CreateSetBankerDelScorePacket(&packet, m_nBankerPos, m_BaseScore))
						{
							BroadcastPacketBC(&packet);
							Log.Warning("PGChannelInterface::SetBankerPos", "轮庄模式2：新庄家座位号%d 锅底：%d", m_nBankerPos, m_BaseScore);
						}
						SendCenterBattleInfo(m_nBasePoint);
					}
					else if (m_bankerAnswer == en_AnswerType_No) //连庄剩余底分不变成默认底分
					{
						// 轮庄模式下连庄
						if (sProtocolsMgr.CreateSetBankerPosPacket(&packet, m_nBankerPos))
							BroadcastPacketBC(&packet);
					}
				}
				
			}
			else
			{ // 第一把随机庄家
				std::vector<uint8> vPos;
				std::vector<TablePlayer>::iterator iter, ei = PlayerPos.end();
				for (iter = PlayerPos.begin(); iter != ei; ++iter)
				{
					if ((*iter).status == en_PlayStatus_Ready)
					{ 
						vPos.push_back((*iter).pos);
					}
				}
			
				m_nBankerPos = vPos[RandomUInt(vPos.size() - 1)];
				Log.Warning("PGChannelInterface::SetBankerPos", "轮庄模式：第一把随机庄座位号%d ", m_nBankerPos);
			}
		}
		else if (m_nLoopBankerMode == en_GameMode_OverLordBanker && m_nLoopId ==1)
		{ // 霸王庄

			std::vector<TablePlayer>::iterator iter, ei = PlayerPos.end();
			for (iter = PlayerPos.begin(); iter != ei; ++iter)
			{
				if ((*iter).status == en_PlayStatus_Ready)
				{
					uint32 pid = 0;
					UserPtr pUser = sUserMgr.load((*iter).player.getResourcePtr()->getUInt32Field("userid"));
					if (!pUser.isNull())
						pid = pUser->getUInt32Field("platform_id");
					if (pid == m_nFzPid)
					{
						m_nBankerPos = (*iter).pos;
						Log.Warning("PGChannelInterface::SetBankerPos", "房主庄模式：庄座位号%d ", m_nBankerPos);
					}
				}
			}

		}
		else
		{ // 抢庄
			if(m_nLoopId ==1)
			{
				std::vector<uint8> vPos;
				for (uint8 i = 0; i < m_bWantBanker.size(); ++i)
				{
					if (m_bWantBanker[i] == en_LootBanker_Yes)
					{
						vPos.push_back(i);
					}
				}
				if (vPos.empty())
				{
					std::vector<TablePlayer>::iterator iter, ei = PlayerPos.end();
					for (iter = PlayerPos.begin(); iter != ei; ++iter)
					{
						if ((*iter).status == en_PlayStatus_Ready)
						{
							vPos.push_back((*iter).pos);
						}
					}
				}

				if (vPos.size())
				{
					m_nBankerPos = vPos[RandomUInt(vPos.size() - 1)];
					Log.Warning("PGChannelInterface::SetBankerPos", "抢庄模式：庄座位号%d ", m_nBankerPos);
				}
				else
					m_nBankerPos = 0;
			}
			
		}

		PlayerPos[m_nBankerPos].onceBanker = true;
		PlayerPos[m_nBankerPos].banker_count +=1;
		m_bSetBanker = true;

		m_status_endtimer = sXmlDataMgr.GetConfXMLValue("SETBANKER_WITETIME");
		m_curState = en_ChannleState_Shuffle;

		if (sProtocolsMgr.CreateSetBankerPosPacket(&packet, m_nBankerPos))
			BroadcastPacketBC(&packet);
		if(m_nLoopId==1)
		{
			//庄家扣取底分对应的积分
			if (sProtocolsMgr.CreateSetBankerDelScorePacket(&packet, m_nBankerPos, (PlayerPos[m_nBankerPos].curScore - m_nBasePoint)))
				BroadcastPacketBC(&packet);
			Log.Debug("PGChannelInterface::SetBankerPos", "抢庄模式第一局：庄家座位号%d 扣除低分：%d - %d", m_nBankerPos, PlayerPos[m_nBankerPos].curScore, m_nBasePoint);
			m_BaseScore = m_nBasePoint;
		}

	}
	// 玩家抢庄
	bool PGChannelInterface::LootBanker(CharPtr &pChr, const uint8 &op_mode)
	{
		if (pChr.isNull())
			return false;

		WGS_BANKER_INNER_LOCK

		if (m_curState != en_ChannelState_RobBanker)
			return false;

		TablePlayer *pTb = GetTablePlayer(pChr->getHandle());
		if (!pTb)
			return false;
		if (pTb->status != en_PlayStatus_Ready)
			return false;

		//已经操作过了
		uint8 pos = pTb->pos;
		if (m_bWantBanker[pos] != en_LootBanker_Init)
			return false;

		if (op_mode) //如果玩家抢庄
		{
			if (m_bWantBanker[pos] == en_LootBanker_Yes)
				return false;
			m_bWantBanker[pos] = en_LootBanker_Yes;
			++m_nBnkerTimes;
		}
		else //不抢
		{
			m_bWantBanker[pos] = en_LootBanker_No;
		}

		++m_nOptTimes;
		WorldPacket packet;
		if (sProtocolsMgr.CreateGetBankerResultPacket(&packet, pos, m_bWantBanker[pos]))
			BroadcastPacketBC(&packet);
		return true;
	}
	//所有积分
	uint32  PGChannelInterface::EveryScore(std::map<uint32,uint32> tp,const uint32 &Num)
	{
		uint32 everyscore = 0;
		for (uint32 i = 1; i <= Num; ++i)
			everyscore += tp[i];
		//Log.Debug("PGChannelInterface::EveryScore", "总积分:%d", everyscore);
		return everyscore;
	}
	//庄家应答
	void PGChannelInterface::BankerAnswer(CharPtr &pChr, const uint32 answer)
	{
		if (pChr.isNull())
			return;
		if (m_curState == en_ChannelState_RobBanker)
		{
			m_bankerAnswer = answer;
			m_contOrstop = true;
		}
		
	}
	//广播玩家下注情况
	void PGChannelInterface::BroadPlayerChinResult(CharPtr &pChr, std::map<uint32, uint32> numchips, const uint32 &num, const uint32 &surscore)
	{
		if (pChr.isNull())
			return;
		WorldPacket packet;
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		if (sProtocolsMgr.CreateChipInResultPacket(&packet, 1, numchips, num,surscore, (*pTp).pos))
			BroadcastPacketBC(&packet);
	}
	//洗牌测试
	void PGChannelInterface::ShuffleText(const size_t &i)
	{
		m_vecCurCards.clear();
		std::vector<PaiGowType> vecCurCards;
		PaiGowType brand_value1[4] = {{4, true, true}, {6, true, false}, {5, true, false}, {10, true, true}};
		for (uint32 k = 0; k < PLAYER_NUM; ++k)
		{
           vecCurCards.push_back(brand_value1[k]);
        }	
			for (uint32 j = 0; j < PLAYER_NUM; ++j)
			{
				std::vector<PaiGowType>::iterator iter = vecCurCards.begin() + j;
				PlayerPos[i].cards.InsertCard(*iter, m_specialtype);
				PlayerPos[i].Originalcards = PlayerPos[i].cards;
				//m_vecCurCards.erase(iter);
			}

		// for (int i = 0; i < 32; ++i)
		// {
		// 	if (i % 2 != 0)
		// 	{
		// 		m_vecCurCards.push_back(brand_value1[0]);
		// 		m_vecCurCards.push_back(brand_value1[2]);
		// 	}
		// 	else
		// 	{
		// 		m_vecCurCards.push_back(brand_value1[1]);
		// 		m_vecCurCards.push_back(brand_value1[3]);
		// 	}
		// }
		return;
	}
	void PGChannelInterface::SendCenterBattleInfo(const uint8 &baseScore)
	{
		WorldPacket packet;
		// 棋牌圈牌桌相关信息
		Json::Value val;
		Json::Reader reader;
		reader.parse(m_strPlayJsonDataCommon, val);
		//附加数据
		//Json::Value val2 = val["extra_data"];
		val["extra_data"]["typeDi"] = baseScore;
		Log.Debug("PGChannelInterface::CheckGameStart", "typeDi:%d curr_loop:%d ", baseScore, m_nLoopId);
		Json::FastWriter w;
		m_strPlayJsonDataCommon = w.write(val);
		if (sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, m_strPlayJsonDataCommon))
			BroadcastPacketBC(&packet);
	}
	// 群发牌桌消息
	void PGChannelInterface::BroadcastPacketBC(WorldPacket *packet, const uint32 &exceptId)
	{
		std::vector<TablePlayer>::iterator itSeat, eiSeat = PlayerPos.end();
		for (itSeat = PlayerPos.begin(); itSeat != eiSeat; ++itSeat)
		{
			TablePlayer &tp = *itSeat;
			if (tp.player.isNull())
				continue;

			if (tp.player._handle == exceptId)
				continue;

			CharPtr pChr = sCharMgr.getByHandle(tp.player._handle);
			if (pChr.isNull())
				continue;

			sGLMgr.SendProtocolsToChr(pChr, packet);
		}
	}
	// 玩家退出牌桌
	void PGChannelInterface::AllPlayersLeaveRoom()
	{
		WorldPacket packet;

		std::vector<TablePlayer>::iterator itSeat, eiSeat = PlayerPos.end();
		for (itSeat = PlayerPos.begin(); itSeat != eiSeat; ++itSeat)
		{
			if ((*itSeat).player.isNull())
				continue;

			CharPtr pChr = sCharMgr.load((*itSeat).player._handle);
			if (pChr.isNull())
				continue;

			PGCreatureInterface *pChrAI = TO_CREATURE_INTERFACE(pChr->getAIInterface());
			if (!pChrAI)
				continue;
			pChr->setStatus(CharacterStatusFree);
			//离开房间
			pChrAI->SetTownNull();
			pChrAI->SetChannelNull();

			if (m_nDissolveReson == DissolveType_Vote)
			{
				if (sProtocolsMgr.CreateKickeOutNoticePacket(&packet, pChr->getHandle(), KickedOut_GameBegin))
					sGLMgr.SendProtocolsToChr(pChr, &packet);
			}
		}

		
	}
	// 准备或者拒绝开始游戏
	bool PGChannelInterface::AgreeOrRefusePlayGame(CharPtr &pChr, const uint8 &agree)
	{
		WGS_CHANNEL_LOCK

		if (pChr.isNull())
			return false;
		// 错误的操作
		if (agree != enAgreeOrRefuse_Agree && agree != enAgreeOrRefuse_Refuse)
			return false;
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		if (!pTp)
			return 0;

		if (pTp->status == en_PlayStatus_Ready || pTp->status == en_PlayStatus_Start)
			return false;

		bool bInSeat = false;
		if (m_nLoopId == 1)
		{
			std::vector<TablePlayer>::iterator itSeat, eiSeat = PlayerPos.end();
			for (itSeat = PlayerPos.begin(); itSeat != eiSeat; ++itSeat)
			{
				if (pChr->getHandle() == (*itSeat).player._handle)
				{
					bInSeat = true;
					(*itSeat).nAgreeSameIp = agree;
					(*itSeat).status = en_PlayStatus_Ready;
				}

				// 有玩家拒绝
				if (agree == enAgreeOrRefuse_Refuse)
					(*itSeat).nAgreeSameIp = enAgreeOrRefuse_None;
			}

			if (agree == enAgreeOrRefuse_Refuse)
			{ // 玩家起立
				PlayerStandUp(pChr);
				m_nWaitPlayerStartTimer = 0;
			}
		}
		else
		{ // 结算后不能拒绝 只能准备
			if (agree == enAgreeOrRefuse_Refuse)
				return false;

			std::vector<TablePlayer>::iterator itSeat, eiSeat = PlayerPos.end();
			for (itSeat = PlayerPos.begin(); itSeat != eiSeat; ++itSeat)
			{
				if ((*itSeat).nAgreeSameIp)
					continue;

				if (pChr->getHandle() == (*itSeat).player._handle)
				{
					bInSeat = true;
					(*itSeat).nAgreeSameIp = agree;
					(*itSeat).status = en_PlayStatus_Ready;
				}
			}
		}

		if (!bInSeat)
			return false;

		WorldPacket packet;
		if (sProtocolsMgr.CreateAgreeOrRefusePacket(&packet, agree, pChr->getHandle()))
			BroadcastPacketBC(&packet);
		if (sProtocolsMgr.CreatePlayerListPacket(&packet, PlayerPos))
		{
		//	Log.Debug("PGProtocolsManager::CreatePlayerListPacket", "发送玩家信息4");
		//	printf("CreatePlayerListPacket 1 次调用\n");
			BroadcastPacketBC(&packet);
		}

		return true;
	}
	// 检测是否达到可以开始游戏的人数
	bool PGChannelInterface::CheckPlayersCanStatPlayGame()
	{
		uint8 player_num = 0;
		std::vector<TablePlayer>::iterator itSeat, eiSeat = PlayerPos.end();
		for (itSeat = PlayerPos.begin(); itSeat != eiSeat; ++itSeat)
		{
			if ((*itSeat).player.isNull())
				continue;
			//Log.Debug("PGChannelInterface::CheckPlayersCanStatPlayGame", "玩家昵称:%s pos:%d 准备状态:%d ", pChr->getStringField("name").c_str(), (*itSeat).pos, (*itSeat).nAgreeSameIp);
			if ((*itSeat).nAgreeSameIp != enAgreeOrRefuse_Agree)
				continue;
			CharPtr pChr = sCharMgr.getByHandle((*itSeat).player._handle);
		
			++player_num;
		}
		if (player_num < PLAYER_NUM)
			return false;

		return true;
	}

	// 检查游戏开始
	bool PGChannelInterface::CheckGameStart()
	{
		WorldPacket packet;

		std::vector<uint32> playing_chars;
		std::vector<uint32> del_chars;

		// 玩家在2人以上就可以开始游戏
		uint8 start_player = 0;

		// 统计在座位上可以游戏的玩家
		std::vector<TablePlayer>::iterator itSeat, eiSeat = PlayerPos.end();
		for (itSeat = PlayerPos.begin(); itSeat != eiSeat; ++itSeat)
		{
			if ((*itSeat).player.isNull())
				continue;

			++start_player;
		}

		if (start_player < PLAYER_NUM)
			return false;

		//bool bHaveOffLine = false;
		// 检查离线玩家不开始游戏
		std::vector<TablePlayer>::iterator itPlayer, eiPlayer = PlayerPos.end();
		for (itPlayer = PlayerPos.begin(); itPlayer != eiPlayer; ++itPlayer)
		{
			if ((*itPlayer).player.isNull())
				continue;

			CharPtr pChr = sCharMgr.getByHandle((*itPlayer).player._handle);
			if (pChr.isNull())
				continue;

			if (pChr->getStatus() & CharacterStatusWar)
				continue;

			WSSocketPtr sockPtr = pChr->getSocket();
			if (sockPtr.isNull() && !pChr->isNPC())
			{ // 离线
				if (start_player > 0)
					--start_player;

				//bHaveOffLine = true;

				TablePlayer freeP = *itPlayer;
				freeP.pos = INIT_POS;

				m_mapFreePlayers.insert(std::make_pair((*itPlayer).player._handle, freeP));
				(*itPlayer).Init();
			}
		}
		++m_nLoopId;


		m_btLog.loop_id = m_nLoopId;						  // 记录当前轮次
		m_btLog.create_time = sGLMgr.GetCurDateTime(time(0)); // 创建时间

		if (m_nLoopId == 1)
		{
			m_nGameStartTime = time(0);
			m_btLog.use_time = m_nGameStartTime;
		}

		std::map<uint32, TablePlayer>::iterator itFree, eiFree = m_mapFreePlayers.end();
		for (itFree = m_mapFreePlayers.begin(); itFree != eiFree; ++itFree)
		{
			if (itFree->second.player.isNull())
				continue;

			del_chars.push_back(itFree->first);

			CharPtr pChr = sCharMgr.load(itFree->first);
			if (pChr.isNull())
				continue;

			if (pChr->getStatus() & CharacterStatusWar)
				continue;

			if (sProtocolsMgr.CreateKickeOutNoticePacket(&packet, itFree->first, KickedOut_GameBegin))
				sGLMgr.SendProtocolsToChr(pChr, &packet);

			PGCreatureInterface *pChrAiInfe = TO_CREATURE_INTERFACE(pChr->getAIInterface());
			if (pChrAiInfe)
			{
				pChrAiInfe->SetTownNull();
				pChrAiInfe->SetChannelNull();
			}
		}

		Log.Debug("PGChannelInterface::CheckGameStart", "channel[%u] cb_id[%u] loop_id[%u] game start!",
				  m_Unit->getHandle(), m_btLog.cb_id, m_btLog.loop_id);
	
		// 棋牌圈牌桌相关信息
		Json::Value val;
		Json::Reader reader;
		reader.parse(m_strPlayJsonDataCommon, val);
		
			//附加数据
		//Json::Value val2 = val["extra_data"];
		val["extra_data"]["typeDi"] = m_BaseScore;
		if (m_changeBanker)
			val["extra_data"]["typeDi"] = m_nBasePoint;
			
		val["start_time"] = m_nGameStartTime;
		val["curr_loop"] = m_nLoopId;
		Log.Debug("PGChannelInterface::CheckGameStart", "typeDi:%d curr_loop:%d ", m_BaseScore, m_nLoopId);

		Json::FastWriter w;
		m_strPlayJsonDataCommon = w.write(val);

		if (sProtocolsMgr.CreateCenterBattleInfoPacket(&packet, m_strPlayJsonDataCommon))
			BroadcastPacketBC(&packet);

		if (m_nLoopId == 1)
		{ // 玩家列表在开始后就不发生状态以及数量的变化
			sCenterBattleMgr.StartNewLoop(m_btLog.cb_id, del_chars, playing_chars);
		}

		for (itPlayer = PlayerPos.begin(); itPlayer != eiPlayer; ++itPlayer)
		{
			if ((*itPlayer).player.isNull())
				continue;

			//(*itPlayer).nAgreeSameIp = enAgreeOrRefuse_None;
			// 设置角色战斗状态
			CharPtr pChr = sCharMgr.load((*itPlayer).player._handle);
			pChr->setStatus(CharacterStatusWar);

		}
		return true;
	}
	//计算成为过庄家的人数
	bool PGChannelInterface::AllInTurn()
	{
		uint8 becombanker = 0;
		std::vector<TablePlayer>::iterator iter = PlayerPos.begin();
		for(;iter != PlayerPos.end();++iter)
			{
				if((*iter).onceBanker)
					becombanker++;
			}
		if (becombanker==4)
			return true;
		return false;		
	} 
	//广播庄家看其他其他玩家牌信息
	bool PGChannelInterface::BroadLookOtherPlayerCards(CharPtr &pChr,const uint8 &otherpos)
	{
		if (pChr.isNull())
			return false;

		WorldPacket packet;
		std::vector<TablePlayer>::iterator itSeat, eiSeat = PlayerPos.end();
		for (itSeat = PlayerPos.begin(); itSeat != eiSeat; ++itSeat)
		{
			if ((*itSeat).pos == otherpos)
			{
				if (sProtocolsMgr.CreatePlayerLookCardTypePacket(&packet, 0, *itSeat))
					BroadcastPacketBC(&packet);
				(*itSeat).IsLookcard = true;
				//Log.Debug("PGChannelInterface::BroadLookOtherPlayerCards", "被看玩家:%d ",otherpos);
			}
		}
		return true;
	}
	// 玩家起立
	bool PGChannelInterface::PlayerStandUp(CharPtr &pChr)
	{
		if (pChr.isNull())
			return false;

		bool bFindSeat = false;
		TablePlayer stCBP;

		// 找到玩家，从座位上起立
		std::vector<TablePlayer>::iterator itSeat, eiSeat = PlayerPos.end();
		for (itSeat = PlayerPos.begin(); itSeat != eiSeat; ++itSeat)
		{
			if ((*itSeat).player.isNull())
				continue;

			if ((*itSeat).player._handle != pChr->getHandle())
				continue;

			bFindSeat = true;
			stCBP = *itSeat;
			(*itSeat).Init();
			break;
		}

		if (bFindSeat)
		{
			TablePlayer stCBP2 = stCBP;
			stCBP.pos = 0; // 重置座位

			m_mapFreePlayers.insert(std::make_pair(pChr->getHandle(), stCBP2));
		}

		// 发送玩家列表
		WorldPacket packet;
		if (sProtocolsMgr.CreatePlayerListPacket(&packet, PlayerPos))
		{
		//	printf("CreatePlayerListPacket 4 次调用\n");
			BroadcastPacketBC(&packet);
		}

		return true;
	}
	// 玩家发起投票
	bool PGChannelInterface::PlayerSendVote(CharPtr &pChr)
	{
		//assert(0);
		if (pChr.isNull())
			return false;

		WGS_CHANNEL_LOCK

		if (m_nLoopId == 0)
			return false;

		uint32 time_now = time(0);
		uint8 result = enSendVote_Sucess;
		do
		{
			if (m_bVoting)
			{ // 正在投票中
				result = enSendVote_Voting;
				break;
			}

			bool bFind = false;
			std::vector<TablePlayer>::iterator iter, ei = PlayerPos.end();
			for (iter = PlayerPos.begin(); iter != ei; ++iter)
			{
				if ((*iter).player.isNull())
					continue;
				CharPtr tempChar = sCharMgr.load((*iter).player._handle);
				if (tempChar.isNull())
					continue;

				if (!(tempChar->getStatus() & CharacterStatusWar))
					continue;

				if ((*iter).player._handle == pChr->getHandle())
				{
					bFind = true;
					break;
				}
			}

			std::map<uint32, TablePlayer>::iterator fitFree = m_mapFreePlayers.find(pChr->getHandle());
			if (fitFree != m_mapFreePlayers.end())
			{
				bFind = true;
				break;
			}

			if (!bFind)
			{ // 错误的玩家
				result = enSendVote_ErrorPlayer;
				break;
			}

		} while (0);

		Log.Debug("PGChannelInterface::PlayerSendVote", "channel[%u] char[%u] result[%u]",
				  m_Unit->getHandle(), pChr->getHandle(), result);

		WorldPacket packet;
		if (result == enSendVote_Sucess)
		{
			m_bVoting = true;
			// 设置牌桌列表玩家正在投票 无法处理其他操作
			std::vector<TablePlayer>::iterator iter, ei = PlayerPos.end();
			for (iter = PlayerPos.begin(); iter != ei; ++iter)
			{
				if ((*iter).player.isNull())
					continue;

				CharPtr tempChar = sCharMgr.load((*iter).player._handle);
				if (tempChar.isNull())
					continue;

				if (!(tempChar->getStatus() & CharacterStatusWar))
					continue;

				uint32 char_id = (*iter).player._handle;

				stVotePlayer stVP;
				stVP.char_id = char_id;
				if (char_id == pChr->getHandle())
				{ // 发起投票的玩家直接算同意
					stVP.vote_status = voteType_Agree;
				}

				m_mapVotePlayers.insert(std::make_pair(char_id, stVP));
			}

			std::map<uint32, TablePlayer>::iterator itFree, eiFree = m_mapFreePlayers.end();
			for (itFree = m_mapFreePlayers.begin(); itFree != eiFree; ++itFree)
			{
				stVotePlayer stVP;
				stVP.char_id = itFree->first;
				if (itFree->first == pChr->getHandle())
				{ // 发起投票的玩家直接算同意
					stVP.vote_status = voteType_Agree;
				}
				m_mapVotePlayers.insert(std::make_pair(itFree->first, stVP));
			}
			m_nVoteOverTime = time_now + sXmlDataMgr.GetConfXMLValue("VOTE_WAIT_TIME");
			Log.Debug("PGChannelInterface::PlayerSendVote", "channel[%u] char[%u] m_nVoteOverTime[%u] vote size[%u]",
					  m_Unit->getHandle(), pChr->getHandle(), m_nVoteOverTime, m_mapVotePlayers.size());

			// 群发发起投票结果
			if (sProtocolsMgr.CreateSendVotePacket(&packet, pChr->getHandle(), result))
				BroadcastPacketBC(&packet);
			// 通知玩家当前投票结果列表（客户端开启投票结果显示面板）
			if (sProtocolsMgr.CreateVoteListPacket(&packet, m_mapVotePlayers, m_nVoteOverTime - time_now))
				BroadcastPacketBC(&packet);
		}
		else
		{
			// 单独发送失败结果
			if (sProtocolsMgr.CreateSendVotePacket(&packet, pChr->getHandle(), result))
				sGLMgr.SendProtocolsToChr(pChr, &packet);
		}

		return true;
	}
	// 玩家处理投票
	bool PGChannelInterface::PlayerDealVote(CharPtr &pChr, const uint8 &mode)
	{
		if (pChr.isNull())
			return false;
		WGS_CHANNEL_LOCK
		Log.Debug("PGChannelInterface::PlayerDealVote", "channel[%u] char[%u] mode[%u]", m_Unit->getHandle(), pChr->getHandle(), mode);
		if (mode != voteType_Agree && mode != voteType_Refuse)
			return false;

		std::map<uint32, stVotePlayer>::iterator fitVote;
		uint8 result = enVoteResult_Sucess;
		do
		{
			if (!m_bVoting)
			{ // 未在投票进行中
				result = enVoteResult_NotInVoting;
				break;
			}

			fitVote = m_mapVotePlayers.find(pChr->getHandle());
			if (fitVote == m_mapVotePlayers.end())
			{ // 未找到玩家，还没有开始投票
				result = enVoteResult_NotInVoting;
				break;
			}

			if (fitVote->second.vote_status != voteType_NoChoice)
			{ // 玩家已经有过选择
				result = enVoteResult_Voted;
				break;
			}

		} while (0);

		WorldPacket packet;
		if (result == 1)
		{
			// 设置玩家投票结果
			fitVote->second.vote_status = mode;

			// 更新投票列表
			uint32 time_now = time(0);
			uint32 left_time = m_nVoteOverTime >= time_now ? m_nVoteOverTime - time_now : 0;
			uint8 vote_player = m_mapVotePlayers.size();
			//uint8 vote_player = m_nMaxPlayerNum;
			if (mode == voteType_Refuse)
			{ // 拒绝
				uint8 refuse_count = 0;
				uint8 nochoice_count = 0;
				std::vector<uint32> vRefuseCharsID;
				std::vector<uint32> vNoChoiceCharsID;
				std::map<uint32, stVotePlayer>::iterator itVote, eiVote = m_mapVotePlayers.end();
				for (itVote = m_mapVotePlayers.begin(); itVote != eiVote; ++itVote)
				{
					if (itVote->second.vote_status == voteType_Refuse)
					{
						vRefuseCharsID.push_back(itVote->first);
						++refuse_count;
					}
					if (itVote->second.vote_status == voteType_NoChoice)
					{
						vNoChoiceCharsID.push_back(itVote->first);
						++nochoice_count;
					}
					
				}
				
				// 结束投票
				if(!nochoice_count)
				{
					if (sProtocolsMgr.CreateVoteListPacket(&packet, m_mapVotePlayers, left_time, enVoteFinalResult_Continue))
						BroadcastPacketBC(&packet);
					m_bVoting = false;
					m_mapVotePlayers.clear();
					m_nVoteOverTime = 0;
					return false;
				}
				if (sProtocolsMgr.CreateVoteListPacket(&packet, m_mapVotePlayers, left_time, enVoteFinalResult_Voting))
					BroadcastPacketBC(&packet);
				// 重置玩家选择结果
				// for (itVote = m_mapVotePlayers.begin(); itVote != m_mapVotePlayers.end(); ++itVote)
				// {
				// 	itVote->second.vote_status = voteType_NoChoice;
				// }

				Log.Debug("PGChannelInterface::PlayerDealVote", "dsgrdgregergergregfrg");
				

			
				Log.Debug("PGChannelInterface::PlayerDealVote", "channel[%u] char[%u] refuse!", m_Unit->getHandle(), pChr->getHandle());
			}
			else
			{ // 同意
				uint8 agree_count = 0;
				std::vector<uint32> vAgreeCharsID;

				std::map<uint32, stVotePlayer>::iterator itVote, eiVote = m_mapVotePlayers.end();
				for (itVote = m_mapVotePlayers.begin(); itVote != eiVote; ++itVote)
				{
					if (itVote->second.vote_status == voteType_Agree)
					{
						agree_count++;
						vAgreeCharsID.push_back(itVote->first);
					}
				}

				// 全部同意的版本
				if (vote_player != agree_count)
				{
					if (sProtocolsMgr.CreateVoteListPacket(&packet, m_mapVotePlayers, left_time, enVoteFinalResult_Voting))
						BroadcastPacketBC(&packet);
					return false;
				}

				if (sProtocolsMgr.CreateVoteListPacket(&packet, m_mapVotePlayers, left_time, enVoteFinalResult_Dissolve))
					BroadcastPacketBC(&packet);

				m_bVoting = false;
				m_mapVotePlayers.clear();

				m_bGameOver = true;
				m_nVoteOverTime = 0;
				m_nDissolveReson = DissolveType_Vote;
				m_curState = en_ChannelState_GameOver;

				Log.Debug("PGChannelInterface::PlayerDealVote", "channel[%u] char[%u] all agree!", m_Unit->getHandle(), pChr->getHandle());
			}
		}
		
		return true;
	}
	// 房主发起解散牌桌
	bool PGChannelInterface::DissolveChannel()
	{
		WGS_CHANNEL_LOCK

		//assert(0);
		m_curState = en_ChannelState_GameOver;		// 切换到结束状态
		m_bVoting = false;							// 关闭投票开关
		m_mapVotePlayers.clear();					// 清除玩家投票列表
		m_bGameOver = true;

		m_nDissolveReson = DissolveType_Homeowners; // 结算原因

		// 发送系统消息
		WorldPacket packet;
		if (sProtocolsMgr.CreateLocalMessagePacket(&packet, sMsg.getMessage("owner_dissolve_channel").c_str(), sMsg.getType("owner_dissolve_channel")))
			BroadcastPacketBC(&packet);

		return true;
	}
	uint32 PGChannelInterface::GetMaxPlayerNum()
	{
		Log.Debug("PGChannelInterface::GetMaxPlayerNum", "最大人数：",
				  m_nMaxPlayerNum);
		return m_nMaxPlayerNum;
	}
	void PGChannelInterface::Update(const uint32 &p_time)
	{
		if (m_nVoteOverTime)
		{ // 检测投票自动逻辑
			if (time(0) >= m_nVoteOverTime && m_bVoting)
			{
				std::map<uint32, stVotePlayer> tempVotePlayers;

				{
					WGS_CHANNEL_LOCK
					tempVotePlayers = m_mapVotePlayers;
				}

				std::map<uint32, stVotePlayer>::iterator itVote, eiVote = tempVotePlayers.end();
				for (itVote = tempVotePlayers.begin(); itVote != eiVote; ++itVote)
				{
					if (itVote->second.vote_status)
						continue;

					CharPtr pChr = sCharMgr.load(itVote->first);
					PlayerDealVote(pChr, voteType_Agree);
				}
			}
		}

		AIInterface::Update(p_time);
	}
	//重返游戏
	void PGChannelInterface::ReturnRoom(TablePlayer *pTp)
	{
		if (pTp == NULL)
		{
			Log.Error("BDMJAIChannelInterface::ReturnRoom", "pTp == NULL ");
			return;
		}

		CharPtr pChr = sCharMgr.getByHandle(pTp->player._handle);
		if (pChr.isNull())
		{
			pChr = sCharMgr.load(pTp->player._handle);
			if (pChr.isNull())
				return;
		}
		WSSocketPtr socket = pChr->getSocket();
		WorldPacket packet;
		if (sProtocolsMgr.CreatePlayerListPacket(&packet, PlayerPos))
		{
			Log.Debug("PGProtocolsManager::CreatePlayerListPacket", "发送玩家信息3");
			//printf("CreatePlayerListPacket 3 次调用\n");
			BroadcastPacketBC(&packet);
		}
		//各种状态的协议包
		if (m_curState <= en_ChannelState_Prepare) //判断牌桌是否处于准备状态
		{
			Log.Debug("	PGChannelInterface::PrepareUpdate", "进入准备状态");
			return;
		}
		if (m_curState < en_ChannelState_GameOver)
		{
			if (m_bSetBanker) //已经定庄
			{
				if (sProtocolsMgr.CreateSetBankerPosPacket(&packet, m_nBankerPos))
					sGLMgr.SendProtocolsToChr(pChr, &packet);
			}
		}

		//玩家座位号
		uint8 pos = pTp->pos;

		switch (m_curState) //牌桌状态
		{
		case en_ChannelState_RobBanker: //抢庄
		{
			if (m_nLoopId == 1)
				SendTableState(socket, sXmlDataMgr.GetConfXMLValue("ST_WT"));
			else
				SendTableState(socket, sXmlDataMgr.GetConfXMLValue("CT_WT"));

			Log.Debug("PGChannelInterface::ReturnRoom", "返回游戏，正在抢庄状态。。。");
			if (!m_bSetBanker)
			{
				for (uint8 i = 0; i < m_vPlayers.size(); ++i)
				{
					if (PlayerPos[i].status != en_PlayStatus_Ready)
						continue;

					//抢庄情况 定庄信息
					if (m_bWantBanker[i] == en_LootBanker_Yes || m_bWantBanker[i] == en_LootBanker_No)
					{
						if (sProtocolsMgr.CreateGetBankerResultPacket(&packet, pos, m_bWantBanker[pos]))
							sGLMgr.SendProtocolsToChr(pChr, &packet);
					}
					else if (m_bWantBanker[i] == en_LootBanker_Init)
					{
						if (i == pos)
						{
							if (sProtocolsMgr.CreateNoticeGetBankerPacket(&packet, 0))
								sGLMgr.SendProtocolsToChr(pChr, &packet);
						}
					}
				}
			}
		}
		break;
		case en_ChannleState_Shuffle: //洗牌
		{
			SendTableState(socket, sXmlDataMgr.GetConfXMLValue("SHFFLECARD"));
		}
		break;
		case en_ChannelState_CutThrowDice: //掷骰子决定切牌
		{
			SendTableState(socket, sXmlDataMgr.GetConfXMLValue("THROWDICETIME"));
			//发送切牌骰子数
			if (sProtocolsMgr.CreateBroadcastDiceResultPacket(&packet, m_dices1, m_dices2, m_nSpeakPos, PlayerPos[m_nSpeakPos].player._handle))
				sGLMgr.SendProtocolsToChr(pChr, &packet);

		}
		break;
		case en_ChannelState_Cut: //切牌
		{
			SendTableState(socket, sXmlDataMgr.GetConfXMLValue("CUTCARDSTIME")); //下发切牌时间
			if((*pTp).cutcardflag)
				if (sProtocolsMgr.CreateBroadCutResultPacket(&packet, PlayerPos[m_nSpeakPos], m_nSpeakPos, m_cutplayer, sXmlDataMgr.GetConfXMLValue("CUTCARDSTIME"), false))
					sGLMgr.SendProtocolsToChr(pChr, &packet);

		}
		break;
		case en_ChannelState_ChipIn: //下注
		{
			SendTableState(socket, sXmlDataMgr.GetConfXMLValue("CHIPINTIME"));

			if ((*pTp).isOnceChin)
				if (sProtocolsMgr.CreateChipInResultPacket(&packet, 1, (*pTp).mapNumScore, (*pTp).curNum, (*pTp).surplusScore, (*pTp).pos))
					BroadcastPacketBC(&packet);
		}
		break;
		case en_ChannelState_DealThrowDice: //丢骰子决定发牌
		{

			SendTableState(socket, sXmlDataMgr.GetConfXMLValue("THROWDICETIME")); //下发丢骰子时间
			//发送发牌骰子数
			if (sProtocolsMgr.CreateBroadcastDiceResultPacket(&packet, m_dices1, m_dices2, m_nSpeakPos, PlayerPos[m_nSpeakPos].player._handle))
				sGLMgr.SendProtocolsToChr(pChr, &packet);
		}
		break;
		case en_ChannelState_Deal: //发牌
		{
			if (sProtocolsMgr.CreatePlayerLookCardTypePacket(&packet, 2, *pTp))
				sGLMgr.SendProtocolsToChr(pChr, &packet);
		}
		break;
		case en_ChannelState_Move: //摆牌
		{
			TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		
				if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState - 1,  sXmlDataMgr.GetConfXMLValue("DEAL_TIME")));
				socket->SendPacket(&packet);
				if (sProtocolsMgr.CreatePlayerLookCardTypePacket(&packet, 2, *pTp))
					sGLMgr.SendProtocolsToChr(pChr, &packet);
				SendTableState(socket, sXmlDataMgr.GetConfXMLValue("MOVE_TIME"));
				if ((*pTp).IsMovecard)
				{
					// if (sProtocolsMgr.CreatePlayerMoveCardPacket(&packet, *pTp))
					// 	socket->SendPacket(&packet);
				}
				if ((*pTp).IsMovefinish)
				{
					if (sProtocolsMgr.CreateReturnPacket(&packet))
						socket->SendPacket(&packet);

					if(sProtocolsMgr.CreatePlayerMoveCardPacket(&packet, *pTp))
						socket->SendPacket(&packet);
					if (m_curState == en_ChannelState_Move)
					{
						uint8 result;
						if ((*pTp).IsMovecard)
							result = pTp->movecardresult;
						else
						{
							(*pTp).cards = SelfCardsTypeCheck((*pTp).cards, 0, 0, result);
							(*pTp).movecardresult = result;
							Log.Debug("PGChannelInterface::PlayerMoveCardFinish", "直接开牌：%d", result);
							if (sProtocolsMgr.CreatePlayerMoveCardResultPacket(&packet, result))
								socket->SendPacket(&packet);
						}
					}
						
					// if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState - 1,   sXmlDataMgr.GetConfXMLValue("LOOK_TIME")));
					// socket->SendPacket(&packet);
				}
				if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState, sXmlDataMgr.GetConfXMLValue("LOOK_TIME")));
					socket->SendPacket(&packet);
		}
		break;
		case en_ChannelState_LookCards: //看牌
		{

			SendTableState(socket, sXmlDataMgr.GetConfXMLValue("LOOK_TIME"));
			// 下发各个方位牌信息
			if (sProtocolsMgr.CreateBankerLookCardsPacket(&packet, PlayerPos))
				sGLMgr.SendProtocolsToChr(pChr, &packet);
		}
		break;
		case en_ChannelState_CalcWait: //结算
		{//每局结算
			SendTableState(socket, sXmlDataMgr.GetConfXMLValue("GAMEOVER_TIME"));
			if (sProtocolsMgr.CreateRoundPGCalcPacket(&packet, PlayerPos, m_nBankerPos, m_rType, m_BaseScore, true))
				sGLMgr.SendProtocolsToChr(pChr, &packet);
			if (sProtocolsMgr.CreatePlayerListPacket(&packet, PlayerPos))
			{
				//printf("CreatePlayerListPacket 6 次调用\n");
				BroadcastPacketBC(&packet);
			}
		}
		break;
		default:
			return;
		}
	}
	// 赠送互动道具
	uint8 PGChannelInterface::GiveFreeGift(CharPtr &pChr, const uint32 &char_id, const uint8 &gift_id)
	{
		if (pChr.isNull())
			return 0;

		uint32 src_charID = pChr->getHandle();
		if (src_charID == char_id) // 不能给自己赠送鲜花
			return 0;

		uint8 result = 1;
		std::vector<uint32> vRecvCharIDs;

		std::vector<TablePlayer>::iterator iter, ei = PlayerPos.end();
		for (iter = PlayerPos.begin(); iter != ei; ++iter)
		{
			if ((*iter).player.isNull())
				continue;

			if ((*iter).player._handle == src_charID)
				continue;

			if (char_id == 0)
			{ // 给所有玩家
				vRecvCharIDs.push_back((*iter).player._handle);
			}
			else
			{ // 给指定玩家
				if ((*iter).player._handle == char_id)
				{
					vRecvCharIDs.push_back(char_id);
					break;
				}
			}
		}

		// 没有可赠送的玩家
		if (vRecvCharIDs.empty())
			result = 0;

		WorldPacket packet;
		if (result == 1)
		{ // 成功
			if (sProtocolsMgr.CreateGiveFreeGiftPacket(&packet, src_charID, gift_id, vRecvCharIDs, result))
				BroadcastPacketBC(&packet);
		}
		else
		{ // 失败
			if (sProtocolsMgr.CreateGiveFreeGiftPacket(&packet, src_charID, gift_id, vRecvCharIDs, result))
				sGLMgr.SendProtocolsToChr(pChr, &packet);
		}

		return 0;
	}

	void PGChannelInterface::SendTableState(WSSocketPtr &socket, const uint32 waitTime)
	{
		WSSocketPtr wSocket = socket;
		int32 offset = waitTime == 0 ? waitTime : (waitTime - (time(0) - m_beginWaitTime));
		// 下发牌桌状态
		WorldPacket packet;
		if (sProtocolsMgr.CreateTableStateUpdatePacket(&packet, m_curState, offset < 0 ? 0 : offset))
			wSocket->SendPacket(&packet); //发送数据包
	}
	bool PGChannelInterface::CurNum(CharPtr &pChr,const uint32 curnum)
	{
		if (pChr.isNull())
			return false;
		WSSocketPtr socket = pChr->getSocket();
		// 通过角色数据获取玩家的牌桌数据
		TablePlayer *pTp = GetTablePlayer(pChr->getHandle());
		(*pTp).curNum = curnum;

		return true;
	}
}